Closed tagyoureit closed 1 year ago
Hey, thanks for opening this issue!
Generally-speaking, I'm on board with a TypeScript conversion. I got a wild hair and tried to teach myself TypeScript a while back, but Real Life™ got in the way and I kinda stopped working on it: https://github.com/parnic/node-screenlogic/tree/dev/typescript
I'd love to integrate this and tag a v2 so long as it keeps working with the primary audience, which is my MagicMirror plugin (which I am happy to make changes to) https://github.com/parnic/MMM-ScreenLogic, the Homebridge integration (which maybe isn't alive anymore?) https://github.com/schemers/homebridge-screenlogic, and the web interface https://github.com/mikemucc/screenlogic-api
I definitely can help work out more commands if there's stuff to be added, especially if you/others are in it with me. :)
Do you know how often a ping needs to be sent to keep a connection to the server?
My MagicMirror plugin sends a ping every minute currently, which works. I remember trying a few different values and 5mins was definitely too long, but a 1-minute ping has been working for probably 6mo now, so that was good enough for me.
What's the difference between the clientId and senderId?
The senderId is an arbitrary number which comes back in the response to any given command to allow you to track multiple requests in flight simultaneously. The clientId is an arbitrary number that allows you to unregister/remove an added client later. So: sender id is for the current message only, client id is for the lifetime of a client session.
I'm getting bad parameters trying to run the following: set circuit state, set circuit run time, delete schedule by id, set schedule
Interesting, if you've got a repro I could help look into it. I use Set Circuit State quite a bit.
12504 is async message that the intellibrite is changing colors (~16s)
👍
I got the bad parameters working. I forget that I normalized the indexes to start at 1 (circuitId - 499; schedId - 699). Just had to add them back. That's what I get for working on this late at night.
I'm going through the equipment configuration and already finding a few items to clean up/add.
Making a bunch of progress... this is all coming directly from ScreenLogic. This system only has basic circuits, but I already have done the chemistry, chlorinator, equipment/controller config, time... Still need to do the pumps, finish the schedules, and then have njsPC send the commands out to SL.
Happy Thanksgiving! It's time to test. 😄
I'm still working on a dev branch, so please follow these directions: nodejs-Poolcontroller
git clone -b 8.0.0 https://github.com/tagyoureit/nodejs-poolController.git
npm i
npm start
dashPanel (in a new terminal window)
git clone -b 8.0.0 https://github.com/rstrouse/nodejs-poolController-dashPanel.git
npm i
npm start
You can us PM2 if you want to monitor/restart the services automatically and keep them running in the background. There are still times when the underlying socket goes down and it is tricky to catch but PM2 will restart the app if it fails.
One you have the apps running, open a browser to http://localhost:5150
. It should look like the following:
Nixie is the name of our standalone controller. But we want to connect with Screenlogic so go to the config (gears) -> Controller tab -> Screenlogic. Click enabled and enter your SL address (it should get picked up after 10s and this wait time can definitely be reduced). If your unit is local and is found you can click the button to copy the address to the system name field.
The app should load all of the system, controller, circuit, intellichlor, schedule, intellichem, pump, etc information...
Nearly everything should be enabled. This includes turning circuits on/off, changing circuit configurations, intellibrite, etc. The only thing I need to go through and check (that I know of) are setting the pump circuits. Everything else that can be done via Screenlogic should be able to be don through the app.
Of course there are likely to be some bugs, so please keep that in mind as you test. But that's also why I'm asking for your testing - to fix any bugs you might find.
cheers!
I'm able to load up the app and find the device through the config page, but every time I try to save, I get:
Error: Login Failed
at UnitConnection. (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:450:16)
at Object.onceWrapper (node:events:627:28)
at UnitConnection.emit (node:events:513:28)
at UnitConnection.onClientMessage (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:570:14)
at UnitConnection.processData (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:346:14)
I do get an appropriate host found Local Screenlogic: Pentair: xx-xx-xx found at 10.0.0.148:80
I'm assuming you have no password, correct? If you do not have one, it doesn't matter.
Can you also try a remote connection with the same system name (for now)? It should be able to login, but just go through the gateway instead of local.
I'm traveling through the weekend so will look at this again when I get back but I was able to log in to my local system so will need to see what it thinks is happening.
Full stack:
Error: Login Failed
at UnitConnection. (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:450:16)
at Object.onceWrapper (node:events:627:28)
at UnitConnection.emit (node:events:513:28)
at UnitConnection.onClientMessage (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:570:14)
at UnitConnection.processData (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:346:14)
at Socket. (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:250:12)
at Socket.emit (node:events:513:28)
at addChunk (node:internal/streams/readable:324:12)
at readableAddChunk (node:internal/streams/readable:297:9)
at Socket.Readable.push (node:internal/streams/readable:234:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
My system does have a password (edit: but a local login doesn't need a password, only remote gateway logins do). Remote login, through Nixie, also fails:
Error: Login Failed
at UnitConnection. (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:450:16)
at Object.onceWrapper (node:events:627:28)
at UnitConnection.emit (node:events:513:28)
at UnitConnection.onClientMessage (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:570:14)
at UnitConnection.processData (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:346:14)
at Socket. (/Users/chris/dev/nodejs-poolController/node_modules/node-screenlogic/index.ts:250:12)
at Socket.emit (node:events:513:28)
at addChunk (node:internal/streams/readable:324:12)
at readableAddChunk (node:internal/streams/readable:297:9)
at Socket.Readable.push (node:internal/streams/readable:234:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
I can connect with local or remote login through node-screenlogic's example script.
Can you please attach the console output? I will clean these up and add them to the official logs but haven't gotten that far. (Your system name will be logged in there so remove that first.)
And just for kicks, what version of Node are you running?
dashPanel:
poolControllers:
> node --version
v18.12.1
Seems like maybe it's only attempting a remote login through the pentair gateway and isn't able to connect directly to the discovered local IP?
Errr, strange. Can you try running with DEBUG=sl* npm start
? Your original debug statements should come through. It's not clear from the logs why it's failing esp. when it can connect with the sample code. I'm able to connect remotely here (will test local connection next week). Pls paste the output here? (I don't need the dashPanel output, just njsPC.)
This is what I'm seeting:
You can also go into the Controller->RS485 tab and disable the port so it doesn't try to open that. It will just continue to flood the logs with error messages.
@tagyoureit are you running node 18. If you are then the socket libs may need updating. I messed around with node 16 and was disappointed that they changed the underlying bindings for socket io. I assume you are connecting with raw sockets. Try installing node 14 to see if it sends an empty auth header correctly.
@parnic on the rs485 tab uncheck enabled for the primary port.
Yeah, it's connecting to the dispatcher even when set to local.
[11/25/2022, 6:01:06 PM] info: [6:01:06 PM] 127.0.0.1 GET /config/options/screenlogic?null {}
sl:find Screenlogic finder searching for local units... +0ms
sl:find Looking for ScreenLogic hosts... +2ms
sl:find found something +7ms
sl:find type: 2, host: 10.0.0.148:80, identified as Pentair: xx-xx-xx +0ms
sl:find Screenlogic found unit {"address":"10.0.0.148","type":2,"port":80,"gatewayType":2,"gatewaySubtype":12,"gatewayName":"Pentair: xx-xx-xx"} +0ms
sendScreenlogicStats set to true
[11/25/2022, 6:01:06 PM] warn: Inactivity timeout for 0 serial port /dev/ttyUSB0 after 10 seconds
[11/25/2022, 6:01:06 PM] error: Error opening port 0: Error: No such file or directory, cannot open /dev/ttyUSB0. Retry in 10 seconds
[11/25/2022, 6:01:09 PM] info: [6:01:09 PM] 127.0.0.1 PUT /app/screenlogic {"enabled":true,"type":"local","systemName":"Pentair: xx-xx-xx,"password":1234,"status":"","readyState":"","connecting":"","destroyed":"","bytesReceived":null,"bytesSent":null}
sl:remote connecting to dispatcher... +43s
sl:remote connected to dispatcher +12ms
sl:remote received message of length 41 and messageId 18004 +18ms
sl:remote it's a gateway response +0ms
sl:remote Gateway request to close. +1ms
sl:remote Gateway request to close. +0ms
sl:remote Gateway closed +0ms
sl:remote Gateway closed +0ms
[11/25/2022, 6:01:09 PM] info: Screenlogic: Unit Pentair: xx-xx-xx found at 23.253.89.11:9934
sl:unit connecting... +42s
sl:remote Gateway server connection closed (close emit) +8ms
sl:unit connected, sending init message... +9ms
sl:unit sending challenge message... +1ms
sl:unit received message of length 32 +242ms
sl:unit it's a challenge response +0ms
sl:unit challenge string emit +0ms
sl:unit sending login message... +0ms
sl:unit received message of length 8 +33ms
sl:unit it's a login failure. +0ms
sl:unit loginFailed +0ms
[11/25/2022, 6:01:09 PM] error: Screenlogic error: Login Failed
[11/25/2022, 6:01:09 PM] error: Login Failed
@tagyoureit The problem is that your loginAsync()
has this.password
as a number type instead of a string. So when it passes the password in, it isn't able to encode properly. If I force the password in dist/index.js to new Encoder('1234')
everything works. This is some logging I added to dist/index.js
async loginAsync()
to see what was up:
debugUnit(`pw: ${this.password} ${this.password.length} ${typeof(this.password)}`);
sl:unit pw: 1234 undefined number +0ms
edit: well, in addition to using remote login even when set to Local. :)
Looks awesome when it's all connected and working, though! I see everything filled out correctly. Very cool!
Ah! Yes, thank you. The data is usually resolved from dashPanel to njsPC as a string but in this case it was happy to send a number. Nice catch. I updated both the node-screenlogic and njsPC to account for this.
You can run a git pull
in the njsPC directory, but you will also need to re-pull the node-screenlogic module. The easiest way to do that is blow away the node_modules
directory and re-run npm i
.
@tagyoureit are you running node 18.
@rstrouse - I tried with both node 16 and 18. The node-screenlogic uses the underlying net.socket module. The only place we would see any change would be between dP<-->njsPC and I haven't noticed anything awry there, luckily.
Looks good! 👍
Thoughts on where to publish the Typescript branch? Happy to post it under my account as a project or if you want to keep it under your account that would work, too.
Also, have you ever tried to snoop on the packets to set the pump speeds? Looks like it should be 12586 but don't know the right format. I imagine I could get wireshark up and running to snoop on the packets but wanted to ask first.
I'd be happy to bring it into my main branch and declare a 2.0. I'm pretty unfamiliar with it, though, so if there's a packaging/distribution process, that would probably be good to know.
I already have support for message 12586. In the current main branch, it's called SLSetPumpFlow.
There are quite a few changes, as you saw. First, I need to start working on the updated readme. But it should work standalone and also as a module (like I'm using it). For anyone else that is using your original code, there will be breaking changes to get it to work with the 2.0 version.
Let me check out the SLSetPumpFlow further. I was having some issues and will let you know.
I updated a bunch of the docs. When you are ready to pull, you should probably save the current master as a separate branch so folks that may not want to update can reference.
I could also not get the SLSetPumpFlow to work. If you get a chance to help me look into, that would be appreciated.
Sorry it took me a while to get back to this. If I run the following, it appropriately sets my first pump's first circuit's flow rate to 2010 RPMs:
const ScreenLogic = require('./index');
connect(new ScreenLogic.UnitConnection(80, '10.0.0.148'));
function connect(client) {
client.on('loggedIn', function() {
this.setPumpFlow(0, 0, 2010, true);
}).on('setPumpFlow', function() {
client.close();
});
client.connect();
}
Changing the second 0 in setPumpFlow to a 1 sets the flow rate for my spa, and changing the first 0 to a 1 sets circuits on my second pump appropriately. I can see it changing in the Pentair ScreenLogic desktop app (for PC) after running the script.
Maybe different kinds of pumps behave differently? Or it's a GPMs vs RPMs thing?
Attached my Wireshark capture. This is the ScreenLogic desktop app setting pump 0 circuit 0 to 2010 RPMs. My machine is 10.0.0.3 and the pool equipment is 10.0.0.148. SetPumpFlow.zip
Also if you want to go ahead and open a PR for your Typescript conversion, I can start working on getting a v1 branched and that pulled in as a v2.
@tagyoureit
I just jumped on the beta bandwagon. Good news is that it does find my Screenlogic adapter (one of them, as I have two but later on the subject of two Screenlogics) I do not have a password and I am getting an error as well. HomeScreen of the dash panel is generic (none of my devices/settings), which is normal provided that the connection failed with the Error below.
Error: Login Failed at UnitConnection. (/home/ivan/nodejs-poolController/node_modules/node-screenlogic/index.ts:484:16) at Object.onceWrapper (node:events:627:28) at UnitConnection.emit (node:events:513:28) at UnitConnection.onClientMessage (/home/ivan/nodejs-poolController/node_modules/node-screenlogic/index.ts:604:14) at UnitConnection.processData (/home/ivan/nodejs-poolController/node_modules/node-screenlogic/index.ts:342:14) at Socket. (/home/ivan/nodejs-poolController/node_modules/node-screenlogic/index.ts:405:16) at Socket.emit (node:events:513:28) at addChunk (node:internal/streams/readable:324:12) at readableAddChunk (node:internal/streams/readable:297:9) at Socket.Readable.push (node:internal/streams/readable:234:10) at TCP.onStreamRead (node:internal/stream_base_commons:190:23)
It is working now !!! I did setup a password and that was it.
@tagyoureit
Thanks for the great idea and brilliant implementation and thanks to @parnic for making it possible.
Here is some feedback.
My particular system shown above has 2 Pentair Controllers in master-slave configuration. The reason for two controllers is that the system manages two bodies of water that are at 200 ft distance. So we installed one controller per site, not that we have that many pumps or devices to manage. The two controllers do not matter for the purpose of Screenlogic (SL). SL does see larger number of devices and features most of which are unused. The whole system has 5 pumps. 3 are hooked to the master controller and 2 are hooked to the slave. However, two of the 3 pumps that are hooked to the master are controlled by on/off relays (circuits) As a result Screenlogic sees 3 pumps total - Pool pump plus the 2 pumps hooked to the slave.
Problems.
None of the above problems is a game changer for me. Those are minor mostly naming and grouping issues
Questions.
Thanks, Ivan
@tagyoureit
I have serious problem. The poolController stops with this error after only 3-4 minutes of working
Error: read ECONNRESET at TCP.onStreamRead (node:internal/stream_base_commons:217:20)
My particular system shown above has 2 Pentair Controllers in master-slave configuration
Can you tell me more about this? I wonder if some of the missing circuits are due to your configuration. I've never heard of Intellitouch in master/slave mode and there isn't anything in the manuals about this. How are they "connected"?
- I have only 4 features set in Screenlogic. The actual features correspond to features 2, 7, 6 and 5 above. For some reason the screen above shows 7 features instead of 4.
You can go into the config (gears in upper right) and go to circuits and hide any circuits that you don't want to see. There is not a 1:1 correlation between how SL shows the circuits and how we show them.
How do I turn on/off circuits and features shown on the screen above by MQTT directly?
https://github.com/tagyoureit/nodejs-poolController/wiki/Bindings-Integrations#mqtt
How do I setup a second Screenlogic adapter in the system?
You can't. This app is designed to control a single pool system. You would need to setup two separate njsPC installations to control each ScreenLogic. But again, I'm not clear on your configuration and how the 2 systems interact and whether you are controlling both systems from one SL or you use both. Can you send some screenshots?
I also need to add logging to the ScreenLogic system. We log everything with RS-485 which allows us to find issues quickly. I'll work on adding this and then will ask you for a replay.
I had some issues with the ECONNRESET previously, but some recent changes I made are supposed to capture that. Can you make sure that you have the most recent code? Run the following in the njsPC directory:
git pull
npm rm node-screenlogic
npm i tagyoureit/node-screenlogic#typescript
@tagyoureit
Thanks for the prompt response. Understood.
My major major major problem now is that the controller doesn’t last more than 2-3 minutes. I can’t do anything. As far as I downloaded it 2 days ago I think that I’m on the latest version but will do the upgrade procedure later today anyhow.
I will also provide screenshots of my SL later today.
I’ll appreciate it greatly if you look into the error that stops the controller after 2-3 minutes of working.
Thanks,
Ivan
@tagyoureit
Attached below are screenshots of ScreenLogic setup menu showing how dual controller system looks in ScreenLogic. Nothing fancy. As you can see it shows two "main" load centers. To your credit your software managed to recognize all circuits from both load centers.
As far as connection between them goes they are connected by the 4 wire connection (same that is used for everything else). Two conductors are for power and the other two RS485.
@tagyoureit
P.S. Followed your advise to update. I got a message "Already up to date" when running "git pull" so I assume that I have the latest version of the Controller.
Ah, now I got it... master/slave is different load centers, of course. You have no idea how rare it is that we see these. You are probably the second person. If you are able to do a replay capture with the rs-485 that would be amazing and I can check things out there. If you are also open to allowing me to remote into your system with ScreenLogic I can also see what's going on. I'd also be able to see with a replay from that, but again, I have to add that to the code.
@tagyoureit
Yes, you are more than welcome to connect to my computer by AnyDesk and poke around to see what is going on. Let me know when do you want to do it by e-mail to admin at zumungo dot com
... also you can connect to my ScreenLogic adapter remotely to see what's going on. Please let me know.
@ivanvach Pull the latest on njsPC (steps 1-4) and dashpanel (step 1 & 4 only).
git pull
npm rm node-screenlogic
npm i tagyoureit/node-screenlogic#typescript
git pull produced errors in both directories Controller and Dashpanel
Tried to correct by
git stash git pull git stash apply
not sure this is the right thing to do.
When I start them Both controller and dashpanel show version 7.7.0 ofter the upgrade. Is this right.
Good news is that it shows all 3 pumps now. Bad news I can't activate any circuit getting this error everywhere
TypeError: Cannot read properties of undefined (reading 'setCircuitStateAsync') at SLCircuits.setCircuitStateAsync (/home/ivan/nodejs-poolController/controller/comms/ScreenLogic.ts:1080:33) at ITTouchCircuitCommands.setCircuitStateAsync (/home/ivan/nodejs-poolController/controller/boards/EasyTouchBoard.ts:1531:31) at /home/ivan/nodejs-poolController/web/services/state/State.ts:300:55 at Layer.handle [as handle_request] (/home/ivan/nodejs-poolController/node_modules/express/lib/router/layer.js:95:5) at next (/home/ivan/nodejs-poolController/node_modules/express/lib/router/route.js:144:13) at Route.dispatch (/home/ivan/nodejs-poolController/node_modules/express/lib/router/route.js:114:3) at Layer.handle [as handle_request] (/home/ivan/nodejs-poolController/node_modules/express/lib/router/layer.js:95:5) at /home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:284:15 at Function.process_params (/home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:346:12) at next (/home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:280:10) at /home/ivan/nodejs-poolController/web/Server.ts:719:25 at Layer.handle [as handle_request] (/home/ivan/nodejs-poolController/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:328:13) at /home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:286:9 at Function.process_params (/home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:346:12) at next (/home/ivan/nodejs-poolController/node_modules/express/lib/router/index.js:280:10)
Also good news is that PoolController doesn't die after 2-3 min work as it used to.
Bad news "screenlogic" tab is missing and the dash shows "initializing" status forever.
Sorry - moved the ScreenLogic settings into the Controller->Comms tab.
Is this a fork of your main poolController software to connect to @parnic 's library or did you make your main one to go both ways RS485 and/or Screenlogic.
The njsPC app can now speak to both RS-485 and SL with @parnic's library. It is just the 8.0.0 branch now but once stabilized it will be pushed back to the main branch.
Sorry it took me a while to get back to this. If I run the following, it appropriately sets my first pump's first circuit's flow rate to 2010 RPMs:
const ScreenLogic = require('./index'); connect(new ScreenLogic.UnitConnection(80, '10.0.0.148')); function connect(client) { client.on('loggedIn', function() { this.setPumpFlow(0, 0, 2010, true); }).on('setPumpFlow', function() { client.close(); }); client.connect(); }
Changing the second 0 in setPumpFlow to a 1 sets the flow rate for my spa, and changing the first 0 to a 1 sets circuits on my second pump appropriately. I can see it changing in the Pentair ScreenLogic desktop app (for PC) after running the script.
Maybe different kinds of pumps behave differently? Or it's a GPMs vs RPMs thing?
Attached my Wireshark capture. This is the ScreenLogic desktop app setting pump 0 circuit 0 to 2010 RPMs. My machine is 10.0.0.3 and the pool equipment is 10.0.0.148. SetPumpFlow.zip
I did get this one working, thanks!
EDIT: This is the right call for the typescript
branch: let pumpRes = await client.pump.setPumpSpeedAsync(1, 1, 2000, true);
. This would set the 2nd circuit in the array of the first pump to 2000rpm. I have all the ID's starting at 1 so SL would natively call this pump 0. On all the API's to get the status (and set the equipment) the same 1 based ID's are used. The index for the array of the pump speed is a bit whacky, but it is what it is.
FWIW, this API call works for this page:
I believe, when you get to the setup you need to send the full equipment configuration:
On a separate note, can you write up the instructions for doing a Wireshark capture (maybe in a wiki entry)? I try to do them but always get a bit tripped up and would really like to use this to decode some other config packets. That would be uber helpful!
Yeah, I think those two screens you show are sending different message IDs, the "setup" page, I believe, is the undocumented Equipment Configuration message that https://github.com/parnic/node-screenlogic/issues/26 exists for.
I'm not sure if I'll have time to write up Wireshark instructions, but maybe. I kinda have to fumble my way through it every time I need to do it again as well, haha. It would largely be the same as any other Wireshark tutorial. Usually I use the decompiled Android app source as my go-to for understanding how messages work, but some, such as SetPumpFlow, aren't implemented in that app and require Wireshark to figure it out.
The APK can be grabbed at any app re-hosting site such as https://apkpure.com/screenlogic-connect/com.app.pentair (or https://apkpure.com/screenlogic-config/com.app.pentair_slconfig for the Config app) and then decompiled with a tool such as JADX or similar https://github.com/skylot/jadx
I'm definitely using both APK's and they are super helpful. Meanwhile...
https://user-images.githubusercontent.com/1646840/209222418-07e162ec-b6ab-4e7a-814e-64b7329e39a2.mp4
(I'm only polling the pump speeds - unless I'm missing it I don't see an async method for this. This is where WireShark would be useful ;)...) The app reflects the new speed at the end of the video .
No, I don't think I'm processing the async addClient() callback for adjusting pump speeds. I'm sure there's something for it. The library logs any unrecognized messages it gets, which might be a starting point.
I have "subscribed" via the addClient method. It sends over the equipment config (and a few others, I believe -- need to get a list), but I am manually polling the pumps for updates. I'm not seeing anything (besides 8300, which isn't related) that is being proactively sent.
@tagyoureit were you ready to open a PR for the typescript conversion?
Hey @parnic! This is long overdue, but I'm finally at a place where I can integrate direct Screenlogic control into nodejs-poolController. I've been wanting to dig into this for quite a while.
To that end, I've gone through and converted all of your code to Typescript + Promises. It still supports the events, too. I've published this up to my repo at https://github.com/tagyoureit/node-screenlogic/tree/typescript. I've changed quite a bit (event names, data structure, return values, etc etc). I can keep this as a separate repo if that makes more sense. I haven't updated the docs yet but the example.ts shows how to use all of the methods.
First question is whether or not you are ok with moving to Typescript + Promises or you would rather keep the plain 'ole Javascript.
Second question is do you have any bandwidth to flush out more of the commands?
I'll also be able to help debugging/decoding many of the other aspects as I've got in-depth knowledge of how the RS485 packets work.
I've got a short list of items that I've compiled so far, but haven't gone through everything to validate it yet. Need to put it through a fine tooth comb.