Skip to main content

Socket library for querying and extracting data from Veeder-Root TLS systems.

Project description

Veeder-Root TLS Socket Library

This is an unofficial Python sockets wrapper for querying Veeder-Root automatic tank gauges remotely through the Internet. This wrapper is primarily made to support the TLS-3xx and TLS-4xx series of automatic tank gauges.

You can install this library on your machine by running pip install veeder-root-tls-socket-library.

If you believe there is something about this library that can be improved upon, please feel free to submit a issue or a pull request. I will do my best to respond to any inquiries promptly.

Commands

The commands used to interact with Veeder-Root TLS-4XX series systems can be found in the Serial Interface Manual in the docs directory of this repository. You will want to look through Section 5 to get a better idea of how commands are sent, Section 6 to see how the responses are formatted, and Section 7 to see the available functions and their specific outputs. This is exactly the same for the TLS-3XX series apart from the available functions.

You will want to use either the Computer or Display format of the function as listed under the Command Format header. For example, if you would like to use function code 101 (System Status Report) in the Display format, you would use the command I10100 to do so. You do not need to add the start of header CTRL + A to the command as this is automatically prepended when using my wrapper, as is the end of tranmission character CTRL + C. If your TLS system needs security codes in front of the commands, then you would simply type the security code before the command.

Examples

This script demonstrates how you can programmatically connect to an automatic tank gauge system and get a system status report. Note that this uses the synchronous TlsSocket -- we also have AsyncTlsSocket.

Script

from veeder_root_tls_socket_library.socket import TlsSocket

tls = TlsSocket("127.0.0.1", 10001) # initial connection
response = tls.execute("i10100") # get system status report

print(response)

Output

"2312301342020402"

This output shows the response from the TLS system. The data 2312301342020402 is provided to you through the execute() function as a string. You can see that the start of header \x01, the original command i10100, the checksum separator &&, the checksum FB3B, and the end of transmission \x03 have all been automatically stripped from the output for your convenience. The checksum is automatically checked against the output and a ValueError is produced if the integrity check fails.

Review the Veeder-Root Serial Interface manual provided with your model of automatic tank gauge for information about how response data is structured for each function. The serial interface manual for the TLS-4XX systems is linked at the beginning of this Markdown file.

I have also created various functions that can be used to query information from TLS-3XX systems and output a Python dict object rather than the raw output that is typically given by these systems. This serves well for extracting specific bits of data from these commands (e.g. the ullage of a specific tank).

Script

from veeder_root_tls_socket_library.socket import TlsSocket
from veeder_root_tls_socket_library import tls_3xx

tls = TlsSocket("127.0.0.1", 10001) # initial connection
raw_response = tls_3xx.execute("i10100") # get system status report
response = function_101(raw_response) # function_101() used to transform raw response

print(response)

Output

{
    'year': 24, 
    'month': 5,
    'day': 26,
    'hour': 16,
    'minute': 14,
    'alarms': [{
        'alarm_category': 2, 
        'alarm_type': 5, 
        'tank_number': '01'
    }]
}

This looks much more readable than a string of numbers! By using these dedicated functions, you can have this data more readily accessible through a Python dict object. Another notable upside of this is that strings and floats are converted by these functions as well, so you do not have to worry about implementing your own IEEE-compliant hex to float function like I did.

The downside of this is that not every TLS-3XX function code has been added yet. Please feel free to submit a feature request or pull request with additional functions if you would like them added to my library.

As an example of an asynchronous script, review the simple script below!

from veeder_root_tls_socket_library.async_socket import AsyncTlsSocket
from veeder_root_tls_socket_library.tls_3xx import function_201
from veeder_root_tls_socket_library.tls_3xx import function_602

# Pulls raw tank data from the tank leak system, including product codes.
async def pull_tank_data(ip: str) -> list:
    try:
        # Instantiate a TLS socket connection.
        async with AsyncTLSSocket(ip) as tls_socket:
            print(f"Connected to {ip}.")

            return {
                "ip": ip,
                "success": True,
                "i60200": await tls_socket.execute("i60200"),
                "i20100": await tls_socket.execute("i20100")
            }
    
    except asyncio.TimeoutError:
        print(f"Connection to {ip} timed out.")

    except:
        print(f"Connection to {ip} failed.")
    
    return {
        "ip": ip,
        "success": False
    }

async def main():
    # Asynchronously pull tank data from the tank leak systems.
    ip_list = [
        "1.1.1.1", 
        "2.2.2.2", 
        "3.3.3.3"
    ]
    tasks = []

    for ip in ip_list:
        task = pull_tank_data(ip)
        tasks.append(task)
    
    results = await asyncio.gather(*tasks)

    # Convert raw command responses into Python dictionaries.
    for result in results:
        if result["success"] == True:
            result["i60200"] = function_602(result["i60200"])
            result["i20100"] = function_201(result["i20100"])
        
        print(result)

if __name__ == "__main__":
    asyncio.run(main())

Using the TLS Client

You can also use the tls_client.py file that I created for this library to interact with the automatic tank gauge systems through a command line interface, similar to how you would with other systems through Telnet, SSH, or Putty. This is not currently included with the PyPI distribution.

you@computer:/$ python tls_client.py "127.0.0.1" 10001

You are connected to 127.0.0.1 using port 10001.

>>

From here, you can type in any function code to interact with the TLS system. As an example, you can type in I10100 to output a system status report in display format, and i10100 to display a system status report in computer format. The required start of header CTRL + A is automatically prepended to your command, so you do not need to worry about that.

>> i10100
2312301229020402

>> I10100 
DEC 30, 2023 12:29 PM

GAS STATION
1234 GAS LANE
HOUSTON, TX
H07188463105001

SYSTEM STATUS REPORT

T 2:OVERFILL ALARM

>>

The time between responses will vary based on how large the responses are. The response for a command like i10100 will be significantly smaller than that of I11100. I have implemented a dynamic waiting function to stop receiving response data once the end of transmission character is hit. If this is not hit, the program will raise an error after waiting for a bit.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

veeder_root_tls_socket_library-2.0.0.tar.gz (25.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file veeder_root_tls_socket_library-2.0.0.tar.gz.

File metadata

File hashes

Hashes for veeder_root_tls_socket_library-2.0.0.tar.gz
Algorithm Hash digest
SHA256 eec71f62372fe78d8068f2d09da1ab6ee1317f08f5c6f16ef31507e365187ee4
MD5 e6ad23b2ebe314c19e8361830d86bd88
BLAKE2b-256 cd8d22ab58fa5706eec0eb3d7d4d972e5aef5348b5846432eb4ea4f7798968e2

See more details on using hashes here.

File details

Details for the file veeder_root_tls_socket_library-2.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for veeder_root_tls_socket_library-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 630f8d8d898f3df53b391ae8af20f9f06846c3bb96d6ccf938e54279aa721982
MD5 0d4e57cd9395b7b55d2c178e4a7f4a66
BLAKE2b-256 de57fbc03a6d5615aeb6fd6768527b4f561ae68e15916a3ebe9e7e344922cffe

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page