tagyoureit / nodejs-poolController

An application to control pool equipment from various manufacturers.
GNU Affero General Public License v3.0
327 stars 97 forks source link

Documenting Pentair Intellivalve communications #363

Open jeffegg opened 3 years ago

jeffegg commented 3 years ago

Describe the bug Not really a bug, more of a feature enhancement. And maybe this isn't the correct place for this, maybe the wiki would be better. Let me know Currently (as I understand) the intellivalve is minimally supported in nodejs-PoolController. In my copious extra time, between family and work, I decided to see what I can do to help improve support. So I ordered an extra intellivalve when adding some to my pool in hopes that I can help this out. Seems I am able, looking at the hardware, there is a PIC16F1718 inside (Yay), as well as a ICSP port, so using MPLABX and an ICD4, I dumped the FW. I'm currently in the process of dissembling the FW from using MPLAB, and Ghidra (thanks NSA :)) I don't know what will be supported, but since I actually made the valve do something from message Center based on the FW (reset) maybe I can figure out something useful, like setting new endstops, etc. Else, I've reverse engineered a partial schematic for the valve and I'll write my own FW. Both efforts will probably take a few weeks, depending on work schedule. FYI I use Pool controller in Nixie single body mode, and I don't have a Pentair panel to reverse engineer communications (assuming the panels have some interesting support.) This would be easier to capture packets and reverse engineer, but I'm not interested in the panel, so don't want to spend the money on it.

Commands I know (as of 10/31/21)

SW reset of valve: Action: 0xF7 (247)

Sent Packet: FF00FF A5 3F 0C 10 F7 04 01 01 F9

 Dissasmbled FW:           
          if (((RX_BUFF_OTHER?[7] == 0xf7) && (RX_BUFF_OTHER?[5] == DAT_DATA_006b)) && (RX_BUFF_OTHER?[9] == 1)) {
                      FUN_CODE_32aa(1); // Not sure what this does yet
                      reset();
_DAT_DATA_006b // Looks to be the valve address, I'm guessing with multiple valves we probably can address, mine is set to 0xC(12) by default._ 

Response Packet: Source: 12 (Valve); Dest: 16(OCP), Action: 1, Data Length 1: 247, Header [165,1,16,12,1,1] Term: [0,167]

tagyoureit commented 3 years ago

Hi and welcome. Interestingly enough, there are no Pentair outdoor control panels (OCP's) that communicate with the Intellivalve via RS485 yet. The valves work exactly like the Jandy valves in that they operate on a +/- DC voltage. The valves are more accurate (less drift over time) but for whatever reason Pentair has not released this functionality to the world yet. @rstrouse started a project over 1 year ago, valve-Grooter, to try and brute force it. There are a number of packets (245, 247, 240/241) that do things but we were never able to put them together in any sequence that would set or move the valves. We did brick a number of them and after sending 10's of millions of messages we eventually gave up. If you continue to find more in the FW, we can triangulate, but it will take someone with your skills or Pentair to help un-stuck us from our progress so far.

Check out the repo above and see if it matches up with your findings and/or if it helps you figure anything else out.

jeffegg commented 3 years ago

Thanks! I knew there was an effort before to brute force it, saw it on some forum. But I was unable to re google it. I just started on the 240 command :). Good news is I have the original FW saved, before even hooking up the RS485, so if I brick something I should be able to recover assuming I don't wear out the flash (doubtful). I could remove the unit if I did this, but this part is on a 6 month to 1 year lead time it seems. Thanks for the link will see what I can do.

rstrouse commented 3 years ago

Good luck. I am not so sure that flash isn't the failure point. Maybe we hit something that trashes the firmware but it didn't seem that a byte sequence sent the valve south. It appeared to be based on how long the valve was having 245 and 247 messages written, We never did see anything that would tell us what the current status of the valve is.

Btw the voltage on the pins is 24vac not dc.

jeffegg commented 3 years ago

Hmm, well thankfully this valve is dedicated to science, worst case I have an emulator I can solder in till I get some new PICs. I can definitely see places where buffer overflow could overwrite something important.

Commands I can see in the source code: Read Destination = 0xC(12) with a command of 0xf0 (240) This returns a serial number (read from the flash chip and assuming it is unique) plus some other fixed and variable data Valve returns command 0xF1 and an 18 byte payload (here is what mine read): 0080 801F124FD63E 0102FFFF 305B2001 0040 0080 is constant 801F124FD63E look to be the serial number read from flash at valve poweron or reset, also the periodic hail has this 0102FFFF is constant 305B2001 these are variables, but I don't see where these come from yet. 0040 is constant

0x50 (80) This command seems to set the Valves Address. After the valve address is set, we no longer see the hails (at least I think that is what they are.)

Header [165, 63,12,15,80,8] It is important to have the source as broadcast (15 or something else), when it is set to 16 (Panel) the address is reset (not sure if this is because I'm missing something else or just the way it is

Payload [ADDRESS, *(don't care it seems), serial number from hail or the reading 0xF0] so in my case I set the valve address to 0 with 0x801F124FD63E as my serial number [4,0,128,31,18,79,214,62]

Upon sending that I get back a broadcast packet from the valve with Source as address above (0x4) destination Panel(16), Action of 1, and payload of 80

image

0x51 (81) I don't know what this does, but it only works when the valve address is 0xC. I haven't really dug into it yet.

I'm still not seeing output when I do anything to the valve, but I suspect there is something else I need to set, will take some more time to continue to disassemble

jeffegg commented 3 years ago

Still haven't done anything useful, but wanted to document this in case anyone tries. There are some commands that can be run at valve startup when the mode light is blinking blue: If you write an action of 245 (0xF5) with payload bytes 2 or bytes 3 not equal to 0, the valve is put into some odd mode (only sends the Hail command, keeps resetting, and buttons don't work.) This command writes the eeprom address 0x41 to 0xFE. Not sure what this command is for yet, but if you see the mode lights blinking blue and valve is useless, you can send something like below to recover (the rest of the payload may or may not matter, mainly sending bytes 2 and 3, to change the EEPROM address 0x41 0xFD, and get out of the odd mode image

rstrouse commented 3 years ago

Yes you have found the blinky blue mode. Originally I thought this might be the valve waiting for input from the master but never could get anything else out of it. I have a one valve stuck in blinky blue and another in modified watermelon mode. I'll see if I can break those out of their respective mode this week using the command above.

Here is some background on our results.

Action 82

This message is referred to as "I am Groot" simply because when we were initially sending messages to the valve this is the only response we got from the valve. It is broadcast from the valve periodically, regardless of whether it is asked for by the master. So it is not a response to a request from the RS485 master. There is one other device that does this and it is iChlor. Both of these appear to fire this off to address 12.

All groot message payloads are unique to the valve and there are similarities for the first several bytes of the payload if the valve is manufactured around the same time. We spent quite a bit of effort to try making sense of this output by comparing it to the label on the valve. Nothing meaningful was gleaned from that other than it looked like you could determine whether one valve was older or younger than another and byte(5) was sequential for valves purchased about the same time.

Action 80

Action 80 appears to set the address by sending the desired address in the first byte followed by the valve key. The valve key is the last 6 bytes of the groot payload. Upon successfully setting the address the valve will respond with an ACK (action 1) payload 80 from the address you assigned.

Action 240

This is an interesting message. When you send an action 240 to the valve using the address it will respond with a 241 message that contains the unique valve key followed by an additional 10 bytes tacked to the end of it which was identical for all valves found in the wild.

So if you have multiple valves on the bus and send an action 240 to 12 then all valves that have not been addressed will respond with a 241 containing the unique key and some sort of status bytes. If the valve loses power and is not stuck in a reboot cycle from 245 or 247 then it will revert to address 12. Address 12 appears to be a general broadcast address for several Pentair equipment items in the wild.

Action 241

Action 241 is a response message. This is a message that is sent from the valve when requested by an action 240. It never shows up unless it is asked for (like a good RS485 citizen). It also honors the proper addressing once you set an address with action 80. The payload for this message has been identical for all valves in the wild and has not changed unless the valve is in a mode where it no longer responds to the buttons on the valve.

This payload is in the form with constant data between all valves witnessed as follows [0, 0, <6 bytes for the valve key>, 1, 2, 255, 255, 48, 91, 32, 1, 0, 64]. This is true unless the valve is stuck in blinky blue then the payload changes to [0, 0, <6 bytes for the valve key>, 255, 255, 1, 0, 48, 91, 32, 1, 0, 64].

Action 247

Action 247 will cause the valve to start the blue light on the valve blinking (blinky blue). When this message is sent to the addressed valve with a payload staring with [1, 2, ...] it will respond with an ACK[247].

If you send enough of these to the valve then it will stay that way and continue rebooting. The human interface on the valve will no longer respond but the valve will continue to respond to messages. Like mom used to say if you keep making that face it will be stuck that way. That is what happens after you have beat the valve up with 247s. However, one of the tests I am going to perform is to send the 245 message again to see if I can break free from the blinky blue on one of the valves stuck there.

Action 245

Action 245 seems to create light shows on the red segment leds for the valve positions. By sending different combinations in the payload we seem to be able to get different lights illuminated on the valve. This message responds with an ACK[245] when a combination it seems to like is sent.

For instance, what was identified as watermelon mode could be attained by sending [0, x, x, x, x, x, x, x, x, x]. Beating up the valve with these messages eventually gets you into carrot mode. Where it doesn't carrot all what you send it and it doesn't carrot all which buttons you press on the valve.

We also hooked the valve up to a relay to cycle the valve after different responses, sending action 240 to see if there was a different response (241) from the valve but never got beyond the aforementioned byte changes and the position never seemed to report anywhere.

In the end we gave up after several valves in the wild stopped responding to the buttons on the valve but never got to the point where the RS485 responses stopped. The only thing I can surmise from it is that the valve either is gets stuck with bad data on it or we simply wore out the flash by writing several hundred million messages to the same locations. There has to be some persistent storage on this valve or it would not remember endpoints or the current mode selected when power is lost.

Bear in mind we hammered this with a brute force method since the firmware code was not available from the valve itself.

jeffegg commented 3 years ago

"There has to be some persistent storage on this valve or it would not remember endpoints or the current mode selected when power is lost." There is persistent storage in 2 places: 1) I only see this being read, never written to, but still disassembling (this will take some time, not friendly to go from hex to pic assembly to c code without context. There are a few spots in the code where values are pulled from the code binary. I'm guessing these are some const values. 2) There is a 5 pin i2c eeprom onboard I missed it at first, I was expecting 6 pins and mistook it for something like a linear voltage regulator. I cannot decode the package marking, but soldering down some probes and hooking up an oscilloscope, plus what I see from the dissembled code this seems to be some 24xxx eeprom. I need to pull this image in case I mess something.

On a good note I was able to get some rs485 traffic to emit when the valve changes position, I can only do this by writing a data value (inside the pic) when in a debugger and the output on the bus is missing the standard 0xff 0x0 0xff message header. Also good news is that each step and direction seem to have different values. I'm trying to trace the writing for this variable but not seeing this, yet. I think the dissembler is messing up bank selects somewhere but will take some time to trace. It is also possible that this is some type of manufacturing mode for ADC calibration (the valve uses a pot to set the position).

Blinky blue mode reminds me of a firmware update mode, but I haven't found proof of that yet. It could also be a mode where the rs485 gets exclusive access to the valve...

Also to note there are 2 different rs485 handlers (I call them early handler and main handler) and they are a bit different from each other. When the valve is powered on, or reset the early handler is used it hands off to the main handler after the valve blinks blue a few times and before the red position and green mode light come on. Based on this I'm wondering if there is some flow expected by the valve for a handshake: 1) Look for the hails from the valve (action 82) 2) Set valve address (action 80) 3) Reset the valve (action 247 with payload = 1) 4) listen for hail on reboot(action 82) 5) reconfigure valve address (action 80) 6) send action 245 mode to put into remote/rs485 exclusive mode. This action only seems to be available in the early handler, but again could be missing somethibg 7) then send some commands to program valve. 8) move to the main flow with updated and saved info. I'm really speculating here, I don't know the normal pentair handshakes, etc. Was trying to think how I would do it if I were to rewrite the firmware

rstrouse commented 3 years ago

It is interesting that if you send a 240 out to address 12 all valves will respond with a 241. However, if you have a bit of RS485 understanding the notion of multiple slaves responding to a single master message is very messy and unreliable in that every valve responding at once can destroy the response from all of them. I suspect the default address is simply set to 12 and it blindly responds when it sees that address.

Since there is no selector to identify a valve address, perhaps our groot message (82) is the only viable option. So it is likely that the OCP will take however long to listen for groot messages on the bus for all unassigned valves addresses but only after it has assigned the ones already defined in the current definition. The valve does appear to inspect all 80 messages for the 6 byte key to determine if it is the intended recipient. The only way to get this key is by listening for the valve to broadcast it. To verify whether the address has been properly assigned you can send a 240 to the assigned address and it should return the valve key.

I suspect that there is a specific address range that Pentair has in mind for these with the most likely address range that starts at 160 and ends at 180. This puts the equipment identifiers outside of other equipment on the bus and provides a contiguous 20 address range that covers all potential valves available with 3 power centers. It could go as high as 24 with reserved addresses for specific valves such as intake, return, and heater bypass.

So a likely sequence would be set all the addresses already assigned by sending action 80 on OCP boot verifying each one by calling 240 for verification using the newly assigned address. This 241 result will match the valve key to the assigned address. The address is critical since the address can only a single byte and the valve key is 6 bytes. This is also critical for the OCP configuration since the valve configuration on the OCP needs to map to a single byte ordinal on one of the 15 valve messages output by the OCP. This too is speculation but it does match up to how Pentair addresses and manages other equipment on the RS485 bus.

Rumors are that there will be 5 slots in the Pentair programming so the valve would have 5 potential endpoint pairs. What is weird is how they would expect to engage these given the current 1 to 1 nature of the assignments where 1 circuit is assigned to each valve. If the circuit/feature is on then the valve is moved to the diverted position. This is done by simply applying power to either the red or white wire via an SPDT relay. The motor simply rotates until the valve reaches the assigned endpoint.

So it is assumed that turning on a circuit or feature will look at all running features associated to the valve and perhaps re-program the endpoints on the valve before engaging it using the relay. How it determines which endpoint slot to use is a mystery. As I look at the operation of the valve the endpoints seem to come in pairs but the only thing that would seem to matter would be the diverted position on the valve. No matter how you slice it if all the associated circuits are off then the un-diverted position would always be the same.

To make this really useful you would want a scenario where the valve endpoint is dependent upon multiple circuits being engaged. For instance, if the waterfall and the fountain are on divert more water to the feature plumbing. I could see a scenario where the max diverted position is calculated by identifying all circuits/features that are currently on and picking the largest diverted position value. This is in line with the way VS/VF pumps work.

jeffegg commented 3 years ago

Documenting a bit more on action 241 (response to 240) in normal mode: Here is what is written by the FW, I have figured out all the info there. My valve returns the following in hex: 0080 801F124FD63E 0102FFFF 305B2001 0040 0080 is constant in code 801F124FD63E look to be the unique ID of the valve read from flash at valve poweron or reset 0102FFFF is constant in code 305B This is the Device ID of the PIC chip (305B is a PIC16F1718 for reference) 2001 This is the Device Revision ID of the PIC chip 0040 is constant in code

Slow going trying to disassemble and fixup code, and try to infer behavior. Unfortunately not seeing anything in code for control of the valve, but I still have about 60% of the code as unknow behavior. Best I was able to do was to get some RS485 traffic to be sent when changing valve locations and modes, etc. I suspect this is a factory test mode, it can be entered by pressing and holding the Mode and Red button through a power on. Then you need to send a certain RS485 packet to enter the mode. After that the valve basically operates as normal, but sends out RS485 messages on valve change (though buttons) but they dont have the typical Pentair header (255 00 255). Still working on it, but dont hold your breaths this is going to take awhile.

jeffegg commented 3 years ago

DANGER DANGER DANGER!!!! For those playing around with sending codes to the valve Blinky blue mode entered by sending action 245 with Bytes 0 and 1 non zero is a Firmware update mode. FW update packet looks like: DATA (values are in HEX): 01 02 - What I choose to enter blinky mode 2A 00 - This writes the microcontroller program memory at 0x1500 (PIC use a fixed 16 bit opcode, so 0x2A00 / 2 => 0x1500) xx xx - Not sure if these matter yet, I wrote 0x1 0x2 and didnt see anything happen, I suspect these are just "filler" Bytes after this are written to memory, will use 0 if these bytes are not sent, expecting 64 bytes in total

Please note PIC architecture enforces a whole row (all 64 bytes) to be cleared, so if there is an unalinged write, bytes not written will fill with 0xFF3F (default memory values in erased memory)

I think there is some protection in FW update mode to prevent some overwrite memory I'm guessing for the boot loader. Code for this protection is a bit confusing, trying to understand.

So if the boot loader is protected, we should be able to recover bad valves through the RS485 port. If someone is interested I can probably write a small program to reflash the firmware(FW).

Also this means another option that can be discussed is to write a custom FW for njsPC to control the valves, if I continue to find the valve doesn't allow SW control. It is possible Pentair didn't finish the code and decided that if they want this control later they can upload a new FW.

rstrouse commented 3 years ago

Well that certainly jives with our experiences. I have 2 valves that are inop after beating it with 245s.

jeffegg commented 2 years ago

Got stalled on this update with my day job (that oddly is also a night job as well most days) and family. I don't think Pentair finished the code for remotely controlling the value (doesn't mean it doesn't exist and I'm missing it.) I've gone through the FW a few times, and there is a basis there for remote control but missing some of the actual code to send and receive the data. I'm moving towards writing my own firmware(FW), there is a bootloader on the valves to do FW updates via the RS485 lines, and I have some rough python code here: https://github.com/jeffegg/IntelliValveFWUpdater to do updates. If people need to revive their dead valves this could potentially help. Unfortunately I'll have to rewrite most of the code for the valve, I'm considering to see if I can just hack in the support with what is there. But I think this will restrict the implementation too much; but still in the back of my head

I'll probably stage the features out like this:

  1. Get basic "remote" access using red and white wires. (Full swing, i.e. 1 side open the other closed); buttons on valve would not work
  2. Report changes in valve status, and ability to poll status
  3. Remote access via RS485 to override red/white wire selections (still full swing)
  4. Support "set mode" to allow setting non full swing via buttons (both relay driven and RS485 would respect these points)
  5. Support more of Intellivalve feature set
  6. ...

If people are interested in this alternative, I can open to the community on what features, how things are implemented, etc. And to obviously share.

tagyoureit commented 2 years ago

If you could make this happen, there would quite a few happy folks out there. I have two manual valves right now that I would never bother to replace with a traditional JVA24 but would do it in a heartbeat with a remotely controlled, variable diverter. One is my spa bypass and the other is the diverter between the floor returns and the wall returns.

My ideal would be to remotely set a fully open/fully closed position. And then being able to send it commands to open a certain amount. Doing this by absolute value would be good (maybe degrees, maybe abs value depending on what you find). Everything that operates based on % just seems hokey (chlorinators, hayward pumps). I should be able to send an RS485 command and have the return diverter fully open (floor returns) when my heater is on full blast, fully closed when my cleaner is running, and somewhere in the middle for just the filter pump running.

johnny2678 commented 2 years ago

This would be huge - as @Tag said, not having remote control is what's keeping me from replacing all my valves with iValves

rstrouse commented 2 years ago

I have 8 IntelliValves currently installed. Happy to help where I can.

mguinness commented 1 year ago

Posted on TFP and thought it would be worth sharing here.

However, the 5-position feature of the IntelliValves will NOT function until Pentair releases the applicable firmware update.

That firmware update is reported now to occur in two phases (Phase I - adding RS-485 support on both the actuator side and IntelliCenter side and Phase II. - more advanced valve controls added to IntelliCenter features.)

Completion of Phase I should occur sometime after this next IntelliCenter firmware update (coming soon) and Phase II completion around Q4 of 2023. It's reported that IntelliValve support is the next major project for the software dev team after this next update.

tagyoureit commented 1 year ago

"I'm sure Pentair will 100% hold themselves to those dates/commitments" - No one, ever.

lol. Will believe it when I see it, but interesting to see some chatter about it anyway.

bluemantwo commented 1 year ago

I was able to buy several Intellivalves on eBay used. The issue with these valves is that they are not made to be repairable. Case is glued shut. Even worse, the internals (gear section) is also glued shut. But I was able to carefully open up 2 of them that had gear problems. The gears are metal, but the shafts are plastic and rather poor quality. Not sure why Pentair designed such expensive actuators that are so poorly made.

@jeffegg , one of the intellivalves had a motherboard that somehow got beat up really bad. Lost most of it's LEDs and push switches, and even a capacitor. But I was able to solder on the capacitor and it appears to operate OK. Just most of the LEDs missing. But if you need a board to mess with and not worry about bricking, I can send it to you.

rock-crusher commented 1 year ago

bluemantwo, think maybe you could post some pictures of the dissected Intellivalves? I think we all would like to see the inside of them. Thank You

tagyoureit commented 1 year ago

@bluemantwo Wow, it's been a few minutes! Glad to see you back here.

jeffegg commented 1 year ago

Sorry I've been super slammed at work for past 9 months. I do have a working firmware I wrote that will actually control the valve and set to a discrete locations via rs485 commands. Local control (buttons and wires with relays) are not implemented. I'm not using in my production environment yet. But on my desk seems stable when I can run once a month or so. I have my code on my local gitlab, but I can upload to the GitHub if there is interest. I also have a python script to upload the FW without using a programmer but this is really not well tested still and have not run in an environment where there are more than 1 device on the rs485 bus.

Here is my setup for debug: PXL_20230130_190846729.jpg

Bunch of pictures of the valve I took: PXL_20211024_074806308.jpg

PXL_20211024_075559466.jpg

PXL_20220629_182600607.jpg

PXL_20211024_075748383.jpg

PXL_20211024_074100386.MP.jpg

PXL_20211024_074745313.jpg

PXL_20211024_074815374.jpg

PXL_20211025_064608453.jpg

PXL_20211025_061809820.jpg

PXL_20211024_074753828.jpg

PXL_20211024_074643057.MP.jpg

PXL_20211024_074652793.MP.jpg

PXL_20211024_074338418.MP.jpg

PXL_20211025_063510456.jpg

PXL_20211024_075603090.jpg

PXL_20211024_074803129.jpg

PXL_20211024_074809676.jpg

PXL_20211024_074740680.jpg

PXL_20211024_075752710.jpg

PXL_20211024_074822336.jpg

PXL_20211024_074342799.MP.jpg

PXL_20211024_074735825.jpg

PXL_20211024_074750151.jpg

PXL_20211025_064549448.jpg

PXL_20211024_074124728.MP.jpg

bluemantwo commented 1 year ago

@bluemantwo Wow, it's been a few minutes! Glad to see you back here.

@tagyoureit LOL. Many, many minutes! How are you doing? I cannot thank you enough for the great work you have done supporting pool automation. I am still using a very old version of your software as my daily driver to run my pool. Only change I have been considering is getting it to update Home Assistant rather than my ISY. Have you done an interface to Home Assistant yet? I should try installing your latest software and give it a test drive. Though I do have a fondness for the initial pre-beta software you did so many years ago.

bluemantwo commented 1 year ago

@jeffegg Please let us know how we can load your firmware. It would be fun to play with.

When you say no local control, does that mean the red/white wires for selecting the 2 valve positions do not work? That would be a bummer since that is what all my existing devices expect. But HUGE thanks for doing this and sharing with us. If we can set the end points using RS485, and then select the end points using red/white wires, we would be golden!

rstrouse commented 1 year ago

njsPC is capable of isolating the valve control to a dedicated RS485 bus if you didn't follow the Pentair preamble sequence.

@bluemantwo - @Crewski has created an integration to Home Assistant that uses sockets and I am working on some pulls for him to add chemistry controller functionality to it as well as schedules.

jeffegg commented 1 year ago

@bluemantwo currently the FW does not support setting valve via the relay interface (red and white wires). Good news is this is completely a FW flow so its possible to add. I plan to make the end stops programmable via RS485 in the future and then have an option to enable/disable the relay interface also via RS485. Basically thinking there will be 3 modes the valve would operate at: 1) "Maintenance Mode" - when in this mode all RS485 control is dropped - valve will still respond to inquires and send out status but not able to remotely move. Good for when you don't want any automation to make your day bad. This mode can be entered via the mode button (actually this is supported today) or via RS485 command. Can only leave via mode button (safety feature) 2) "Relay Mode" - emulate what is there today, but have programmable endstops, status updates, etc via RS485. 3) "Full Automation Mode" - no relays needed; just power via black and either red or white. RS485 can fully control the valve (set current valve position) - this is mostly implemented

I need to start spending some time again on this as work is getting a bit "quieter" and I should have a free evening on the weekends coming up. I need to package up the FW to be loadable via the Pentair booloader. And verify the python code to invoke and use the bootloader. I don't develop this way and usually just write with the programmer

@rstrouse I followed the Pentair packet layout; actually using MessageCenter to send the commands to the valve before I dig into any of the Webcode.

    transmitBuffer[0] = 0xFF;
    transmitBuffer[1] = 0x00;
    transmitBuffer[2] = 0xFF;
    transmitBuffer[3] = 0xA5;
    transmitBuffer[4] = newCommand->protocal;
    transmitBuffer[5] = newCommand->destination;
    transmitBuffer[6] = newCommand->source;
    transmitBuffer[7] = newCommand->command;
    transmitBuffer[8] = newCommand->data_length;
    //DATA
    //CHECKSUM 

Command will be completely of my own creation; this is current "API". Not all command supported yet, and I need to fully document how this works. Here are my proposed commands

// Commands sent by the Valve
typedef enum
{
    VALVE_STATE             = 0x02, // Sent periodically
    VALVE_STATE_CHANGED     = 0x04, // Will Emit when state change finished
    VALVE_DEGREES           = 0x06, // Returns Byte(next position), Byte(0 - moving, 1 not moving), WORD(raw ADC)
    VALVE_DEBUG_DEGREES     = 0x08, // Returns Byte(next position), Byte(0 - moving, 1 not moving), WORD(raw ADC read twice), WORD(neededValue);
    VALVE_STARTING_UP       = 0xE0, // Valve is starting up - Done when 1st VALVE_STATE is sent
    VALVE_RESET_START       = 0xE2, // Valve will emit before resetting if reset command sent
    VALVE_SETTINGS          = 0xE4, // These are the valve settings
    VALVE_SETTINGS_DONE     = 0xE6, // Valve settings have been set and acknowledged
    VALVE_ADDR              = 0xEA, // My address
    VALVE_EEPROM            = 0xEC, // Valve EEPROM Data (For backup)
    VALVE_EEPROM_SET_DONE   = 0xEE  // Valve EEPROM Data (For backup
} rs485_send_commands;

// Commands received by the Valve
typedef enum
{
    //When any change takes place all commands dropped until job finished
    VALVE_GOTO_0_POSITION           = 0x10, // PORT at 0 position is closed
    VALVE_GOTO_24_POSITION          = 0x12, // PORT at 24 position is closed
    VALVE_GOTO_MIDDLE_POSITION      = 0x14, // Move valve to middle position (all open)
    VALVE_SET_DEGREES               = 0x16, // Set a specific value (This between 0 and 0x30, so step size is 180/48=> 3.75)
    VALVE_GET_DEGREES               = 0x17,
    VALVE_SET_DEGREES_FROM_CURRENT  = 0x18,

    VALVE_REMOTE_CONTROL            = 0x20, // Valve will enter remote control mode and accept commands if 1st packet is 1; else exit remote mode

    VALVE_ENTER_MAINTENACE_MODE     = 0x40, // Valve will move to Yellow Led mode and not respond to remote commands that change state/settings
                                            // !!! No way out remotely - for safety/security, need to exit at pad !!! Can also be set at Pad
                                            // Should still emit VALVE_STATE messages periodically with indication of this mode
    VALVE_DEBUG                     = 0xE0, // Enter a debug mode that outputs lots of data -- Use with caution;
    VALVE_RESET                     = 0xF1, // Forces valve to reset; used for FW Update
    VALVE_FW_UPDATE                 = 0xF3, // Enter FW update on next boot
    VALVE_GET_SETTINGS              = 0xF5, // Returns current valve settings (no state)
    VALVE_SET_SETTINGS              = 0xF6, // Sets valve settings (not state)
    VALVE_GET_ADDR                  = 0xF7, // Gets the valves UUID and address (Part of settings but added shortcut)
    VALVE_SET_ADDR                  = 0xF8, // Sets the valves address, need to pass data as UUID (6 bytes), 0x0, newAddr
    VALVE_GET_EEPROM                = 0xF9, // Gets the EEPROM for backup
    VALVE_SET_EEPROM                = 0xFA, // Use with extreme caution - will overwrite EEPROM      

} rs485_receive_commands;
bluemantwo commented 1 year ago

Fan-freakin-tastic! Can't wait. Well, actually, I can. No real rush on this but this is a function I have been wanting for years. Even before the Pentair IntelliValves were released I envisioned something like this. Very cool.

For those who want to plunge into this, there is a guy selling these valves on eBay for about $40 each (try Make an Offer) but sells them as broken. I bought 3 and was able to cobble 2 working ones out of it. Downside is that these are some of the most cheaply made and unreliable devices I have yet seen from Pentair. And I have seen a lot.

rstrouse commented 1 year ago

Awesome! So there are a couple of things that will help let this play nicely on the Pentair bus. First, once the addressing takes place there is no need for a slave to emit anything unless asked. In fact chlorinators can be tardy sometimes when they are polled so they are collision monsters. The software (master) should send a request to the slave (valve) and it should return the expected bytes.

There are a couple of posts on TFP where folks have hooked up 5+ IntelliValves to RS485 and the groot messages appear to degrade their RS485 network. Once the valve is addressed (the one thing we figured out how to do) it stops sending groot messages until asked. It only does this because it is very likely that a broadcast with many valves is likely to end in missing valves. These addresses seemed to persist until you reset them to the broadcast and it would then start grooting again.

I do know what Pentair was going to do wrt the programming. The rumor mill said that there would be 5 sets of position that could be selected by the mode operation on the pool and each would have 2 endpoints. I do not know whether the valve itself stored this information or it was set only by the master. Likely, it stored at least one active endpoint set.

The reason for this is so the valves home to the default position if RS485 is interrupted. The OCP has sort of a halt state that moves everything to an idle state when power is still on and the comms fail. This is also how the service mode operation works.

All of the equipment items do this. So if the watchdog on the pump, heater, or chlorinator doesn't get a message after a specified period of time it will stop. For valves this is currently done in the OCP where it will simply cut coil power to the relay and the valve will move to the home position.

Not that this is the only way to skin this cat but I suspect the flow was going to go like this from Pentair.

  1. Onboard the valve by assigning it an address. Currently (1-16 = System/Controllers, 80-84=Chlorinators, 95-111 = Pumps, 112-127=Heaters, 144-158 = IntelliChem)
  2. Send a position marker at regular intervals to the valve with both endpoints.
  3. Valve responds with the current position
  4. If the position does not match what the OCP expects, continue to poll until the valve matches its expected position.
  5. When the position is reached continue operation and cancel valve delays.

Although I cannot be sure, I suspect that the relay on the OCP is still in play. It simply energizes which leg it wants to match the valve position and the endpoint stop then determines where it should land. There is a thing in the valve programming to reverse it but this is only to accommodate installing the valve 180 degrees either direction.

My belief is that they expect to send in an endpoint pair then energize the diverted or undiverted state depending on the current operation of equipment.

tagyoureit commented 1 year ago

@tagyoureit LOL. Many, many minutes! How are you doing? I cannot thank you enough for the great work you have done supporting pool automation. I am still using a very old version of your software as my daily driver to run my pool. Only change I have been considering is getting it to update Home Assistant rather than my ISY. Have you done an interface to Home Assistant yet? I should try installing your latest software and give it a test drive. Though I do have a fondness for the initial pre-beta software you did so many years ago.

The software has come SOOOO far since those early days. It's almost embarrassing how many times I had to go back and forth to get it right. The software is just amazing now and much of that is due to @rstrouse. We've re-written it since those early days.

There is a Home Assistant plugin but there is an even better one from @crewski https://github.com/Crewski/njsPC-HA and the associated discussion and it can be installed from the HACS repo.

You'll be happy with where we are and never look back at that ancient code again!

bluemantwo commented 1 year ago

@jeffegg , you able to make any more progress?

jeffegg commented 1 year ago

Ok so here is the pre-Alpha-Alpha version of the FW: https://github.com/jeffegg/EggysIVFW/releases/tag/v0.0.0 Wiki for said release: https://github.com/jeffegg/EggysIVFW/wiki/How-to-use-V0.0.0-release I need to document the API on the Wiki, and how to flash it. I only recommend using this on valves not in your "production" environment. I cannot guarantee anything. I'm not releasing FW with this yet; mainly to get the code:

  1. Licensed properly (Will be using GNU Affero General Public License v3.0). I'm using some of Microchip's generated code, and I need to understand the license there as I've run into issues with them specifically releasing some of their generated code before (14+ years ago). I'm tempted to rewrite completely as I've had to edit things anyway to make them work properly.
  2. Documented/cleaned up a bit more - it's a bit dirty. I do plan to get something out ASAP so people can see what is there, even if I need to drop the microchip generated portion.

Moving forward, I think we need to agree on an API, do we design the FW like @rstrouse thinks Pentair is doing or do we go a custom route and make what we want or at least what we think we want. I'm game either way.

I'll work on getting some Wikis going to document using that FW. I was only interacting with it using message manager at this point to send commands, as I follow Pentair's packet formats (or at least the generic header).

bluemantwo commented 1 year ago

Excellent! Thank you!!

jeffegg commented 1 year ago

And sorry I'm slow on getting this out; I am a senior engineer at a large multinational tech company (yay late night and early morning meetings) and between family and work recently, my spare time is mostly zero; I see some light in front of me for some time.

bluemantwo commented 1 year ago

You are a hero for making progress on this. As far as API, I personally have no preference on API direction. It might be nice far, far down the road to have your firmware be able to mimic Pentair's but just add more features that Pentair chooses not to support. Or, at a minimum, ensure your firmware plays nice when on the same RS485 bus as the Pentair system without causing problems. But trying to adjust your API for Pentair firmware that might never come out anyway might be a waste of effort.

I think the primary use case for your firmware will be people using red/white relay control from their automation systems, while using your firmware to dynamically set end points as needed.

Amigaman68 commented 1 year ago

Great work Jeff,

 I looked at the source code zip and it had no source code in it, can i get a copy would love to play with this please?
jeffegg commented 1 year ago

Sorry for radio silence, I've been working way to much(its looking clear) I finally got the code up at https://github.com/jeffegg/EggysIVFW, this is the version I play with at home, really messy written adhoc as I was playing. I would (and do) not use this in a production environment; so again at your own risk.

Here are my plans: 1) Rewrite it all again :). a) Seems many are looking for similar to todays FW with just ability to set b) Emulate Pentair's FW from button/relay control c) Changes/Features over Pentair's FW: 1) RS485 Interface: a) Pretty much start over from what Pentair has right now. b) Non-Provisioned Valve will start with a default address of 0xB3(179), 1) In Auto mode on valve if Red button + save button are pushed at same time, will send hail messages for 5 minutes. Hail message will contain the unique ID(UID from EEPROM) (basically todays "grot" message) 2) Respond to default address + Identify command + UUID with ACK packet + flash all LEDS on valve for 1 minute or address change 3) Respond to default address + address change command + Valve ID = Ack with new address + valve reset c) Provisioned Valve: 1) Follow what @rstrouse was thinking for control: a) Controller will send a "Left" Endstop and "Right" EndStop periodically b) Valve will respond with Current Position and current selected Endstop(allows SW to know/figure out relay hookup) c) If valve position doesn't equal selected (via relay) endstop value move towards it d) If valve position at selected end stop, do nothing 2) Setting for: what happens when no messages from controller happens a) Move to "selected endstop" (endstop may change based on 8) (default) b) --or-- don't move from current position till communication reestablished or user hits yellow + Save button (and then move to current saved endstop) 3) Address change 4) Get Valve UID 5) ID yourself - flash for 1 minute or another ID message is sent (which ever is 1st) 6) FW update mode 7) Debug mode - output more data on RS485, allow dumping EEPROM, etc. 8) Setting for: What end stops to use in provisioned mode + no periodic packets a) Use last set endstop values (either manual or RS485) (Default) b) -or- Set end stop to last manual settings c) -or- Set end stop to last RS485 Values d) I'm thinking that when in provisioned mode + seeing periodic Valve packets: 1) Only 2 modes supported: Automation mode (Auto+Set light on) and Service Mode 2) Service mode will ignore rs485 packets and will respond with current position and in service mode 3) Automation mode will only allow moving to service mode via mode button e) I'm thinking that when in provisioned mode + not seeing periodic Valve packets: 1) act as todays valve, i,e, support button/relay mode 2) RS485: Get current Endstop settings command (helps on 1st time setup or after power outage, etc.) will return what user set on setting mode or what was last set via RS485 (which ever was last controlled)

  1. Write proper I2C and UART (RS485) libraries that have proper error recovery
bluemantwo commented 1 year ago

@jeffegg , please let us know if/when you are ready for any of us to test any of the software you are now working on. I have not tried to install the prior version and prefer to wait for the re-write you are now doing. Good luck, and thanks so much for sharing your work with us.

And BTW, I agree with your logic outlined above, including what to do when in provisioned mode and seeing / not-seeing packets. Very thoroughly thought out. That would be perfect.

jeffegg commented 1 year ago

A little sneakpeak below, I've got 75% of the FW done, at least enough to begin testing and debugging internally. And starting to add some support to test in the apps. I think end of this week or next week. I should have a very rough alpha version to test with following:

Here is what I currently have in my test environment, when intellivalves are added via pool controller and circuits are set, some new settings pop up :). Values for the intellivalve are read from valve via RS485, adding support to set them now from Dash Panel. Needs some UI work still :)

image
bluemantwo commented 1 year ago

@jeffegg , exceptional progress!! Thanks again for sharing and keeping us updated.

I have not yet converted my system to the current nodejs-poolController (still using old code that I heavily modified from several years ago due to my unique system). Any chance of a stand alone version of your IntelliValve software?

jeffegg commented 1 year ago

@bluemantwo are you looking to have a webservice to use that would bind to an open port? Also you would need to have the Valves on a separate RS485 controller. I have a Python Script - This would be simple for me as I have some code already for testing and use this for FW updates right now. But its currently command line driven. I could potentially add an MQTT interface, or do a web service from the python code, I think relatively easy. If you prefer something like nodeJS that's possible - it will be slower to get working as I'm not proficient in JS like I am in Assembly/C/C++/C# and python (nor do I have much server-side web app experience). I'm learning now, just slowly.

bluemantwo commented 1 year ago

Thanks for considering the idea. I use Home Assistant for most things, so would be looking for a way to interface to that. I mostly have written my own python or nodejs code to bridge the gaps, or even just REST interface would help.

But perhaps the best idea for now is for me to have a separate instance of poolController running on my Pi and with a separate RS485 stick talking only to the valves. poolController I believe has a good interface to Home Assistant. That way I am not taking any of your cycles away from the core work you are doing.

But longer term, having the ability to use REST commands to get commands into and data out of your IntelliValve code would really be great. And maybe down the road someone can write a full integration for Home Assistant to your valve code.

Thanks again for helping out the community so that we can finally make full use of our IntlliValves.

bluemantwo commented 1 year ago

Just saw your initial Alpha releases, @jeffegg! I will try to set up my test bench today or tomorrow and provide whatever feedback I can. Is there any tutorial on how to load the firmware? Or is that done within nodejsPC interface?

And what time zone are you in? Even for a west coaster like me, you stay up late!

Cheers!

jeffegg commented 1 year ago

I'm on the west coast as well. Just used to being up late to work with the rest of the world. I'd rather work till 2 then get up at 6. I'm still on pre-alpha releases. I should be ready to get the alpha releases out this weekend. I need to finish testing a few things and fix 1 or 2 critical issues (worst being some positions seem to cause some oscillation in the adc causing continuous valve correction (motor will heat up)). After that I need to document theory of operation, valve commands and responses, known bugs and features that are not implemented. Also need to test deployment of FW, will be a python script I had previously. I use the debug tool to deploy but there is a way built-in the valve for it. And also branch njsPC and Dash Panel to get out my changes to use.

jeffegg commented 1 year ago

So I didn't get much work on Saturday and then hit a bug tonight that is blocking multiple valve when running the new FW - valve address not updating remotely; know the issue, but need some time to fix; and then get the poolcontroller and dashpanel bundled up. FW update is working via script. I hope to get everything out tomorrow late night.

bluemantwo commented 1 year ago

No rush, @jeffegg . Count on me to be a test bench for you when ready. I have a large number of valves (9 last count) that I purchased damaged and was able to repair, so I am happy to set up a test bench with them when you are ready. And if any become bricked, I have plenty to spare.

So take your time, and let us know when you are ready to do more wide spread testing.

Cheers

jeffegg commented 1 year ago

Ok for the brave individuals out there, I did a release on some Alpha level FW for the intelliValves. I plan to take a jump this weekend and deploy to my "production" setup (i.e. my pool) this weekend. I don't recommend anyone to do this, and if you do any issues are on you (though please report). I've been testing mainly with a spare Jandy Valve (to verify correct movement) and some intelliValves. Also, I had 2 valves working and somewhere along the way I think I broke something, so I can only recommend working on one valve. Release is here: https://github.com/jeffegg/EggysIVFW/releases/tag/v0.2.0 I also have a version of pool controller and dash Panel I use for to control it. Please note these versions were really done for me to get a taste of how things work and are blatantly wrong in some areas, and I not all things work for the valve (Adding new circuits for the Valve). I also have not talked to @tagyoureit and @rstrouse on what they were thinking for changes or even how they wanted to handle this. Also I don't know JS/TS (not fully true I mentor some kids that use JS for robots but that is very different from web apps), I know Assembly, C/C++/C#, and Python and mostly from the embedded side. So learning on the fly here; as well as learning how things are setup internally. SW "works" for the most part. Here are my forked versions of the controller SW: https://github.com/jeffegg/nodejs-poolController https://github.com/jeffegg/nodejs-poolController-dashPanel Tomorrow night I'll writeup how to deploy the FW and get everything working. I have a new valve on my desk with the original FW so I can write all steps up correctly.

bluemantwo commented 1 year ago

Thanks again @jeffegg !! This weekend is kind of crazy for me, but I will try to deploy this on my test bench I have set up. Test bench is a single valve, connected to Rpi4, running latest nodejspoolcontroller. I have 3 additional valves set up, but will start with just 1 valve. BTW, if you need an additional valve to test with yourself, I will be happy to send you one which you can keep. I refurbed quite a few and now have extras. Let me know. It is the least I could do.

johnny2678 commented 1 year ago

if you need an additional valve to test with yourself,

I'm just a interested observer with no skills to offer. Thank you @jeffegg for your efforts and thank you @bluemantwo for offering time and equipment to test.

bluemantwo commented 1 year ago

@jeffegg , I see Alpha 0.2.1 is up! Can you provide guidance how how to deploy? I am more python aware than c aware. Thanks, thanks, thanks for sharing your work!!!

jeffegg commented 1 year ago

Here are the instructions, I deployed to a valve twice to verify it works. Let me know! https://github.com/jeffegg/EggysIVFW/wiki/Setting-up-a-new-valve-with-v0.2.1-FW

bluemantwo commented 1 year ago

@jeffegg , following your instructions, I am not getting the blinky blue light when trying to flash the firmware. How do I get into blinky blue light mode?

EDIT: I put it into service mode, and was able to get blinky blue. But it only lasted about 10 seconds, so I had to bring my computer near my test bench to start 2nd command quickly after seeing blinky blue. Now it is flashing. YAY!