ASEKO ASIN AQUA Pool Tech - Data Stream Local TCP & API - Update 12 October 2025

If you havent seen the new announcment from Aseko…

ASEKO LAUNCH PUBLIC API (Sept 2025)

Local is king… however if you want to access your data you send to Aseko, they have an option for that. Asekos Public API.

“The platform enables an automated way of data synchronization for your linked devices to third parties such as home automation solutions or data aggregation platforms. These services could help you monitor your devices better and offer automated actions across environments. However, it is important to note that such integrations are entirely optional and not required for the standard functionality of connected devices.”

Link to API documentation
https://api.aseko.cloud/api/v1/docs

ASIN AQUA Net - Local TCP Buffer :bison: Sizes

Any of you manage to figure out the differences between the various buffer sizes / messages?

The most regular one is the 120. (using)

However you can see a few others popping up but I cant see the patterns and cause

{ “DEBUG”,“local”:“2025-10-13 11:37:59”,“bufferSize”:112 }
{ “DEBUG”,“local”:“2025-10-13 11:38:10”,“bufferSize”:128 }
{ “DEBUG”,“local”:“2025-10-13 11:38:20”,“bufferSize”:120 }
{ “DEBUG”,“local”:“2025-10-13 13:07:49”,“bufferSize”:240}

Aseko isn’t very proactive or helpful sharing any documentation :lying_face:

Local TCP stream Data: Buffer (120) parse - Error index

LATEST UPDATE 2025-11-09

The model ASIN AQUA Net with Redox ORP and pH sensors. Dose Chlorine and pH minus.

I am using Node-Red while I am trying to find out all the data in the buffer and offsets. I am also creating my own functions with Alarms and Notifications via the app and e-mail when the unit indicates an Error. Later when I’ve tried out and tested my function I might move it over to an application.

Data is put through with TCP IN and OUT node. See other post in this thread.

Next up is to try and find a way to track the amount of chlorine and pH minus being used. Track when there is much used or how much is left in the canister.

Still have plenty to figure out. Here is how I got so far.

Remember that this is what I choose to create. There are plenty of other ways, maybe way better. However as I did struggle to get any further to figure out getting the data from the Aseko unit, my idea is to share what I know and you can create what you need, and do it your way.

MAIN FUNCTION NODE - BASIC VALUES


// Extract values from buffer array > payload
const buffer = msg.payload;

// Serial number (4 bytes at offset 0)
const serialNumber = buffer.readUInt32BE(0);

// Settings Pool Volume in cubic meter
const pool_volume = buffer.readUIntBE(93,1)

// Settings Target PH
const pH_target = buffer.readUIntBE(52,1) / 10.0;

// pH value (2 bytes at offset 14)
const pH = buffer.readUInt16BE(14) / 100.0;

// Settings Target Redox
const redox_target = buffer.readUIntBE(53, 1) * 10.0;

// Redox value (2 bytes at offset 16)
const redox = buffer.readUInt16BE(16);

// Water Temperature value (2 bytes at offset 25)
const temperature = buffer.readUInt16BE(25) / 10.0;

// ERRORS! See separated Function Node with Parse WaterFlow & Current Status

// Salinity (not this model)
const salinity = buffer.readUIntBE(20,1) / 10.0;

//  CURRENT TESTS
// Delay Startup ???
const delay_startup = buffer.readUIntBE(74,2);

// Delay ??
const delay = buffer.readUIntBE(30,2);

// Current Power ??
const current_power = buffer.readUIntBE(21,2) / 10.0;

// Payload 
msg.payload = {
    serialNumber: serialNumber,
    poolVolume: pool_volume,
    pH_target: pH_target,
    pH: pH,
    redoxTarget : redox_target,
    redox: redox,
    temperature: temperature,
};

return msg;

SPECIFIC - WATER FLOW STATUS - FUNCTION NODE

Indicates the waterflow status. Value for “ON” and “OFF”
I have a separate node for text (for translation to local language)

// Extract values from buffer array > payload
var buffer = msg.payload;

// Flow to sensors state value (1 byte at offset 28)
var flowState = buffer.readUInt8(28);

// Send ON/OFF status
if (flowState === 0xaa) {
    msg.payload = "ON";
} else if (flowState === 0x00) {
    msg.payload = "OFF";
} else {
    msg.payload = "Unknown";
}
return msg;

SPECIFIC - WATER FLOW STATUS Text English - FUNCTION NODE

To send for display and forward messages in notifications and more.

// Extract values from buffer array > payload
var buffer = msg.payload;

// Flow to sensors state value (1 byte at offset 28)
var flowState = buffer.readUInt8(28);

// Send text from status
if (flowState === 0xaa) {
    msg.payload = "Water flow to Probes OK";
} else if (flowState === 0x00) {
    msg.payload = "Water flow to Probes is OFF";
} else {
    msg.payload = "Unknown Water flow state. Check your unit.";
}
return msg;

SPECIFIC - STATUS WITH ERROR - FUNCTION NODE

The errors listed in the RS485 Protocol + own findings after debug

  • 10 or 15 or 25 doses of pH without a change of pH value (Error 1)
  • 30 doses of CL without a change of CL value (Error 2)
  • no flow to the probes (Error 3)
  • no ph dose too rapid value change (Error 8 based on the buffer data 0x08) Display text: ASIN AQUA stop regulations of pH for 2 hours for safety reasons

Error 4 is now the ‘other’ various, non documented errors. If it follow the RS485 it would be 0x04, but came up as 0x08. What other errors that I havent captured will fall into the various.

My Nodered Function Nodes

I have separated the nodes with Error status code and another with text. This is because it fits better into my flow and functions. You can merge the two and be creative with the payload.

STATUS CODE Add
2025-10-25 Update new finding in the TCP buffer: 0x08 ASIN AQUA stop regulations of pH for 2 hours for safety reasons


// Extract values from buffer array > payload
var buffer = msg.payload;

var stateRead = buffer.readUInt8(13);

// Create a message object to send the status
if(stateRead === 0x00) {
    var stateReadOut = 0; // No Error, all OK
} else if (stateRead === 0x01) {
    var stateReadOut = 1; // Error Code 1
} else if (stateRead === 0x02) {
    var stateReadOut = 2; // Eror Code 2
} else if (stateRead === 0x03) {
    var stateReadOut = 3; // Error Code 3
} else if (stateRead === 0x08) {
    var stateReadOut = 8; // Error Code 8
} else {
    var stateReadOut = 4; // If any other Error
};
// Payload with option to expand
msg.payload = {
    operationState : stateReadOut
};

STATUS CODE in TEXT
Change the string text to something that works with you. Or the local language.

// Extract values from buffer array > payload
var buffer = msg.payload;

var stateRead = buffer.readUInt8(13);

// Create a message object to send the status
if(stateRead === 0x00) {
    var stateReadOut = "Aseko operating status OK";
} else if (stateRead === 0x01) {
    var stateReadOut = "Error Larm! > pH > Too many doses, No value change.";
} else if (stateRead === 0x02) {
    var stateReadOut = "Error Larm! > ORP > 30 doses of Chlorine, No value change."
} else if (stateRead === 0x03) {
    var stateReadOut = "Error Larm! > Probe Readings > Too rapid value change.";
} else if (stateRead === 0x08) {
    var stateReadOut = "Error Larm! > Too rapid change of pH value. Will STOP regulatons of pH for 2 hours for safety reasons"; 
} else {
    var stateReadOut = "Error Larm! > Please check the Aseko display.";
};

// Payload with option to expand
msg.payload = {
    operationState : stateReadOut
};

ERROR CODE HANDLER VER 1 - ASIN AQUA NET!
UPDATE 2025-11-09

This function is dependent on the Status Code function.

I created this handler because there can be more than one State or Error code at the same time. As the buffer index data only delivers one State or Error at the time, the latest, it becomes more difficult to indicate two errors at the same time.

If the chlorine doses are failing and the Redox ORP value dont change the Status or what I call it, the Operation State will be 2, indicating Error-Code 2.
Normally that State or Error will be reset to 0 and the unit will run as normally.

However when Operation State is 2 and another error appears, example that the pH minus dosing fails, it will switch to 1 as the latest. Two error on the unit but only one status/error forwarded.

To be able to handle this I created a function to indicate what errors that are active to be able to show this in the UI and be able to forward a notification and e-mail informing you this is the case.

If there are two errors, the counter will say 2 and the state for every type of error will show true or false.

OUTPUT: The payload that looks like this:

errorStatus: object
  errorCount: 2
  stateErrorCode_0: false
  stateErrorCode_1: true
  stateErrorCode_2: true
  stateErrorCode_3: false
  stateErrorCode_8: false
  stateErrorCode_4: false

To create this I have made a function node with the following code:
NOTE! Change and modify the context storage to work with your setup.

// Multi-Error Tracking Logic v1.1
// Error Code Handler v 1.1 (t/f)

// NOTE Remember to modify the Context Store settings for flow/global to your setup.

// Read Operation State Code (Error code)
let incoming = msg?.payload?.operationState;
let currentCode = Number(incoming);
if (!Number.isFinite(currentCode)) return null; // invalid input

// Known codes (0 means reset/no error)
const KNOWN = new Set([1, 2, 3, 8, 4]);
if (currentCode !== 0 && !KNOWN.has(currentCode)) {
    // Treat any unknown non-zero as "unspecified" error 4
    currentCode = 4;
}

// Load persisted state (Context Store/file storage)
let prevCode = flow.get("01_FUNC_Operation.errorCode", "file");
let activeErrors = flow.get("01_FUNC_Operation.activeErrors", "file") || [];
if (prevCode === undefined) prevCode = 0;

// Timestamp for the latest change will be stored.
const unixNow = Date.now();

// Only act on changes
if (currentCode !== prevCode) {

    if (currentCode === 0) {
        // Rule A: Reset clears all
        activeErrors = [];
    } else if (prevCode === 0) {
        // Rule B: Start — add the first error
        if (!activeErrors.includes(currentCode)) activeErrors.push(currentCode);
    } else {
        // Rule C: Add/Clear between non-zero codes
        if (activeErrors.includes(currentCode)) {
            // We moved to a code that is already active -> previous code cleared
            if (prevCode !== 0 && activeErrors.includes(prevCode)) {
                activeErrors = activeErrors.filter(c => c !== prevCode);
            }
        } else {
            // New additional error becomes active
            activeErrors.push(currentCode);
        }
    }

    // Persist only when a change occurred (Context Store/file storage)
    flow.set("01_FUNC_Operation.errorCode", currentCode, "file");
    flow.set("01_FUNC_Operation.codeChanged", unixNow, "file");
    flow.set("01_FUNC_Operation.activeErrors", activeErrors, "file");
}

// Build msg.errorStatus map (booleans, not strings)
const CODES = [0, 1, 2, 3, 8, 4];
const status = {
    errorCount: activeErrors.length
};
for (const c of CODES) {
    status[`stateErrorCode_${c}`] = (c === 0)
        ? activeErrors.length === 0
        : activeErrors.includes(c);
}

// Payload
msg.errorStatus = status;

return msg;

I haven’t decided on how the errors will be shown in the UI yet.
It needs to be logic and easy to understand. The important part is that it will show all errors, not only the latest one.

The idea of handling the errors like this helps me with working on the notifications that will be sent to both the Home Assistant app and via e-mail.
… thats up next.


DOSING TRACKING VER 1 - ASIN AQUA NET!
UPDATE 2025-10-27

I have been analysing the buffers to find a patterns in values for when the pumps are running, dosing both Chlorine and pH-minus. (Specific for the Asin Aqua Net modell with Redox sensor). Both wont run at the same time however they can be triggered closely.

I have not figured out how to calculate the offset values to get the amount of liquid used. Instead I’ve decided to for another model as version 1.

Vers 1 - Read Timestamps and start/end triggers

I will start extracting when a pump will start and end, reg the timecode and then calculate the duration of the dosing event.
I will figure out by research from using the unit, how much liquid is suppose to be used in milliliter/second. Then calculate the usage for every event and the total usage per day, week, month… and create a function calculating how much of the canister with Chlorine or pH minus have been used knowing when to buy and exchange to a new load.

The function to register start, stop and calculate have been tested today and it works following the data registered on asekos cloud server. They are exactly the same.

As a first step I will share the Nodered Function node “Dosing Detector” that will show how to pick up on start & stop. Later I will share my flow and how you can create a function that will be useful for you, moving data into Home Assistant.

NODE 1: Dosing Detector - CL - Chlorine


// FUNC DOSING DETECTOR ON/OFF > CL Chlorine ---
// WILL ONLY SEND DATA ON A TRIGGER

const dosingChem = "Chlorine";

const DOSE_FLAG_OFFSET = 29;   // confirmed buffert offset for dosing flags
const CHLORINE_MASK = 0x02;    // 0x02 bitmask for chlorine dosing trigger

let lastDoseState = flow.get("10_func_doseSwitch_CL.lastDoseState", "file"); // get prev status from local flow storage
const doseByte = msg.payload.readUInt8(DOSE_FLAG_OFFSET);
const PumpState = (doseByte & CHLORINE_MASK) !== 0;
const inTimeUnix = msg.dateTime?.unix; // reciving date and time from a specific node with timestamp at the event

// Trigger only when state changes. false = OFF, true = ON
if (lastDoseState !== PumpState) {
    flow.set("10_func_doseSwitch_CL.lastDoseState", PumpState, "file"); // save data to local flow storage
    flow.set("10_func_doseSwitch_CL.lastDoseStateTime", inTimeUnix, "file"); // save data to local flow storage

    // Payload for this Trigger
    msg.doseSwitch = {
        time_local: msg.dateTime?.date_f || new Date().toLocaleString(),
        time_unix: msg.dateTime?.unix || Math.floor(Date.now()),
        pumpState: PumpState,
        dosingChem : dosingChem
    };

    // show status in UI
    node.status({ 
        fill: PumpState ? "green" : "gray", 
        shape: PumpState ? "dot" : "ring", 
        text: PumpState ? "DOSING CL ON" : "DOSING CL OFF" 
    });

    return msg;
}

return null;


**NODE 2: Dosing Detector - pH minus **

// FUNC DOSING DETECTOR ON/OFF > Ph Minus ---
// WILL ONLY SEND DATA ON A TRIGGER

const dosingChem = "pHminus";

const DOSE_FLAG_OFFSET = 29;   // confirmed buffert offset for dosing flags
const PHMINUS_MASK = 0x01;    // 0x01 bitmask for pH-minus dosing

let lastDoseState = flow.get("10_func_doseSwitch_pHminus.lastDoseState", "file"); // get prev status from local flow storage
const doseByte = msg.payload.readUInt8(DOSE_FLAG_OFFSET);
const PumpState = (doseByte & PHMINUS_MASK) !== 0;
const inTimeUnix = msg.dateTime?.unix; // Get timestamp data from main time node

// trigger only when state changes
if (lastDoseState !== PumpState) {
    flow.set("10_func_doseSwitch_pHminus.lastDoseState", PumpState, "file"); // store data to local flow
    flow.set("10_func_doseSwitch_pHminus.lastDoseStateTime", inTimeUnix, "file"); // store data to local flow

    msg.doseSwitch = {
        time_local: msg.dateTime?.date_f || new Date().toLocaleString(),
        time_unix: msg.dateTime?.unix || Math.floor(Date.now()),
        pumpState: PumpState,
        dosingChem : dosingChem
    };

    // show status in UI
    node.status({ 
        fill: PumpState ? "blue" : "gray", 
        shape: PumpState ? "dot" : "ring", 
        text: PumpState ? "DOSING pH- ON" : "DOSING pH- OFF" 
    });

    return msg;
}

return null;

That is what I have right now. Later I will share the flows on how to make use of this.

If anyone has a missing bit or have figured out useful data from other buffers please feel free to add your discovery.

Thanks to everyone helping out.
Tack

It seems only GET method has been published.
It is a pitty and not moving us anywhere :expressionless:
We would really need PUT available…

Agree. Feels like they are ages behind. However, at least I’m able to create the priority alarms to grab our attention when something is wrong.

Smart home functions is all to make our life easier. Dont know what is going on as several corp are taking steps backwards instead of moving forward. BMW scrapped their system and making it harder. Only making read available and more difficult to handle. :frowning_with_open_mouth:

Be careful:
The web-backend of my pretty recent Aseko Asin Aqua Salt looks different in Firefox and Chrome. In Firefox I have more options (like choosing POST for communication, removing the “1.php?” from the call to the original address, etc).
On the other hand, all the settings I make get lost, when I reopen the page.
And: The reboot does not work in Firefox.
What worked for me was:
Editing the values in Firefox (removing the php stuff, too) saving (but not reopening: Not quite sure if the values will really get lost on the machine, the textfields are blank though at reload, so after fumbling for hours I’d rather not risk reloading).
Rebooting via Chrome browser.
P.S.: @jmnemonicj : You probably mean “POST” not put, seems you are a developer, but not for the web ;-). You can switch to POST, using Firefox.

Shoutout to everybody who found out about the whereabouts of the bits and bites in the buffer! Thank you all, the flow that was posted above works for me now, even though I would certainly want to change values…

Oooh, what I wrote above was only true, because I have Noscript running in Firefox… :roll_eyes:. That stopped the javascript in the page from hiding some of the configuration options (so nice if people don’t know what they are doing, giving others room for exploitation :wink::
In the source of your USR-Webinterface you find an iframe and the links that are opend in this frame are in the menu. Open the according pages directly in your browser (in my case something like “sernet1.shtml”).
Then, copy the html into a new file and change the action of the form to “http:///config.cgi” (Or whatever it says originally, like “spec.cgi”. The http:// part is vital).
Look for lines with “.style.display=“none”;” and change like that:
document.getElementById(“tcpcshort”).style.display=“table-row”; // .style.display=“none”;
Save the copy and open in browser. Now you will see all options even with javascript enabled and can also send the reset. As the forms use “GET”, you also see the link with all the variables in your address line after submission and can keep it for later, in case you messed up.
With all that said, I still can’t get it to work reliably. Is just works sometimes and quits working after some time “reliably”. Also the passhrough node that sends to ipool / iremote or whatever does not work, evene though I adapted that according to what it said in the backend (“pool.aseko.com:47524/1.php?”).
Example config-link for Aseko Asin Aqua Salt:
http://192.168.X.X/config.cgi?port=0&br=57600&bc=8&parity=1&stop=1&fc=0&tlp=47524&trp=47524&tnmode=1&url1=192.168.X.X&htpurl=&htpghead=User_Agent%3A+Mozilla%2F4.0 Connection%3A+close&htr=User_Agent%3A+Mozilla%2F4.0 Connection%3A+close&htpd=1&srh=1
Replace the IP with yours and you can try to configure without the backend.

@derjoshder you are perfectly right, I was developer, but the web was not my domain :-P. Anyway thank you for the insight :slight_smile:

Your config-link example just show “reset” button. I have Aseko salt as well. Sorry i got lost…
I mean all those parameters are just USR-Web related and no option to POST any change to the underlying ASEKO Salt unit, aren’t they?

Thanks again for the clarification.

Yes, indeed, there does not seem to be an easy backchannel. I’m not going to climb down into the hole at my pool eacht ime I want to switch the pump on / off.
Having trouble with the control of the pump anyways and looking forward to getting some insights by the technican tomorrow.
Still struggling to get it working…
Can someone repost the exact settings in the USR-IOT Backend that work? I’m going crazy, no debugging information in Node red anymore, even though port and everthing should be fine? Do I have to check the RFC2217 Option? What about buffering the data before sending? GET or POST? I erased the URL in the httpd field (1.php?). What the hack is the timeout for…?
Any help appreciated, I managed to find more settings, but am now struggling to get them right :flushed::roll_eyes::man_shrugging:.

Have never heard if anyone manage to do “write” commands to their Aseko non-professional/home-user units.

I wonder if the external/extra display that can be connected via RS485 can be used as a “remote” to make changes to the settings? Similar to the main display. Or is it only a display without the touch function? Can any settings be made/changed from an external unit in any way? I dont know.

Haven’t tried it myself. Aseko has a windows software (Kx cloud communication module) that that can display readings. Wonder if this can debug any kind of commands made to the screen (except from confirming “desired/goal” value sent via the usual TCP/RBS485 stream). See earlier post

It is a shame that there isn’t an obvious way via Remote to write and change any desired or goal values on the Aseko dose units.

Anyone who finds a way, please share.

I don’t know how it works with salt / sanitizes automatic systems? I have the Asin Aqua NET for chlorine and ph minus dosing. I set the goal values in the beginning of the season and they will stay the same for the rest of our season unless there is an issue. No need to stop the dosing pumps unless a problem pops up. Stopping the flow to the sensors is a manual, cut the flow.
There is no way to stop the dosing pumps via a remote user… (what I know of).

My temp solution now is a Shelly that I can remote control from Home Assistant. It will break the power to unit, not ideal and only in an emergency.

Circulation Pump (off the topic)

To turn off & on the circulation pump anyone can use a Shelly that can handle the power (watt) required by the pump.

In my case I’ve built a RS485 remote control with ESPHome that controls our iSaver. On/Off or set the rpm for the pump can be done via the ESP integration + have by built control system in Nodered that is controlled by HA UI. I manage to build this thanks to all the good people here in the community :slight_smile:

Left is the ESP 32 and the RS485 controls connected via cable to the Modbus connectors in the iSaver.

Exactly, climbing down to switch the pump on/of, or change start/end period based on part of the year (my pool is running all the time, even during the winter), or change algicid dosing value is awful.
Anyway, just tell me the steps and I can try to dump those exact settings in the USR-IOT you are looking for.

External display has the ability to control the pump (on/off). The benefit to control the pump through the dosing unit is the ability to stop electrolyzer as well. In other case, there will be a coating on the electrolyer after a while (because running without the water flow) and we have to scrub it or the effectivity of chlorine production will go lower pretty fast :frowning: (and it is dangerous in my opinion as well)

Or you could use just the wifi controlled power socket for the pump on/off functionality only. But the electrolyzer will go on even if pump is off - not optimal, maybe even dangerous as mentioned before…

Agree. Not good enough. The negatives on the equipment and your system are too big. There has bo be a proper option and solution.

If the external screen can control the unit (connected via RS485) it could be done. RS485 can be sniffed, how to figure out how to run the same via TCP might be more difficult.

I’m not too happy to open the unit case. Incase it affects the warranty. But dont think I have a choice if connecting an external screen to the RS485 connectors.

Even though I would buy an external screen, installing it inside our main building, I still want to be able to use smart solutions to control it with Home Assistant.

I’m curious what you can find out from the technician.

That is actually my set-up :slight_smile:

I’m using a basic (“dumb”) pump that can only be switched on or off. To control it, I’ve connected both the pump and the Aseko Salt unit to sockets managed by a Shelly 2PM device. Since they share the same circuit/phase, I can use the output socket on the Aseko Salt unit as a trigger (switch input) for the Shelly. This allows the Salt unit to control the pump as needed — but I can also override it manually if necessary.

Safety Measures

To prevent damage or unsafe operation:

  • :white_check_mark: The Aseko Salt unit is configured with flow detection safeguards. If no water flow is detected, dosing and electrolysis are automatically blocked until flow resumes for a defined period.
  • :white_check_mark: As an additional layer (via Home Assistant), I’ve set up logic to shut down the pump if it’s running but no flow is detected for an extended time.

:warning: Important Disclaimer

Always consult a qualified electrician to ensure your setup complies with local regulations. If you’re not trained or confident in electrical work, leave it to professionals.

I am not sure the flow control sensor is working correctly.
I can see the flow active, even when my pump (controlled by wifi socket) is off.
So maybe it just think it is on because the aseko unit controls the pump an evaluate it as on even it is not.

Or the integration is not working correctly regarding the flow attribute :-/, as the cloud data are just forwarded from the HA integration right now as well.

You can check my screenshot for details:
HA - bazén filtračné… - means wifi socket (Aktívny - Active)
HA - history for the flow is active all the time for the whole day from midnight, even it was on for half an hour after midnight and then off until 8:26, then on util 14:43 And then off again.




Any hints why flow attribute is not rendering corectly?

Testing - analysing buffer

I have been running some more tests and am analysing the buffer data. Making a second deep dive .

Testing is done on the ASIN AQUA NET with Redox.

UPDATE 2025-10-28

The unit is sending the data buffer every 9-12 sec (might be 10 sec)
AND when a dosing pump get triggered, an error happens. This means there will be an accurate timestamp for every event. On this model I cant find a timestamp in the buffer so I’ll create one for when the data is received.
I have tested this and its exactly the same timestamps as the Aseko cloud have register the start and end action.

The first dosing pump, disinfection or the Chlorine can be found in Offset 29.
0x02 bitmask for chlorine dosing
0x01 bitmask for pH-minus dosing.

From this you can create a function setting On / Off.

You can see how I’ve done this in a Nodered Function node (see my post with code)
Link

Are you using the Local application in Home Assistant from HACS?

Is the HA - bazén filtračné… - filter pool?
Switches on and off depending on your time set for start and end?

This is only Speculations. Wonder if there is a discrap in the timecode. Internal vs set in app code? dont know how that application is structured and how it gets triggered on when is on and off.
In my unit there is no timecode sent, I have to create that myself.

@hopkins-tk Do you have a clue?