From 3637862a162be443222866fb2d3766eb825305e5 Mon Sep 17 00:00:00 2001 From: DaveBoettger <42744413+DaveBoettger@users.noreply.github.com> Date: Fri, 14 Jul 2023 14:38:04 -0400 Subject: [PATCH] =?UTF-8?q?Changes=20to=20allow=20for=20reading=20more=20t?= =?UTF-8?q?han=20one=20continuous=20block=20of=20resgis=E2=80=A6=20(#473)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Changes to allow for reading more than one continuous block of resgisters at a time Support reading of bit or bit range within individual registers needed for reading i.e. alarm conditions from the generator controller Configuration file loading switched to read an entire directory of .yaml files at a time * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Replaced lambda function definitions in favor of real function definitions in order to satisify flake8 pre-commit.ci tests. Manual merge executed. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Better documentation Added a configuration section to generator.rst Added sample configuration files in sample_configs directory. Sample interval is now an argument to the agent. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Small changes to docs formatting and args --------- Co-authored-by: David Boettger Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: jlashner --- docs/agents/generator.rst | 77 +++- socs/agents/generator/agent.py | 196 +++++++-- socs/agents/generator/config.yaml | 396 ------------------ .../generator/sample_configs/Alarms.yaml | 121 ++++++ .../generator/sample_configs/Engine_Data.yaml | 193 +++++++++ 5 files changed, 533 insertions(+), 450 deletions(-) delete mode 100644 socs/agents/generator/config.yaml create mode 100644 socs/agents/generator/sample_configs/Alarms.yaml create mode 100644 socs/agents/generator/sample_configs/Engine_Data.yaml diff --git a/docs/agents/generator.rst b/docs/agents/generator.rst index 83a1c073f..69ec2630d 100644 --- a/docs/agents/generator.rst +++ b/docs/agents/generator.rst @@ -29,13 +29,18 @@ using all of the available arguments:: {'agent-class': 'GeneratorAgent', 'instance-id': 'generator', 'arguments': [['--host', '192.168.2.88'], - ['--port', 502], + ['--port', 5021], ['--mode', 'acq'], - ['--read-config', '/home/ocs/CONFIG/ocs/generator-config.yaml']]} + ['--configdir', 'G1_config'], + ['--sample-interval', 10] + ]} .. note:: The ``--host`` argument should be the IP address of the generator on the network. + The '--configdir' argument specifies a directory name for configuration files + relative to the $OCS_CONFIG_DIR environment variable. + Docker Compose `````````````` @@ -59,24 +64,80 @@ The ``LOGLEVEL`` environment variable can be used to set the log level for debugging. The default level is "info". Description ------------ +``````````` On-site generators will be used to provide power to the SO site. -Each generator have the same controller/interface, the Deep Sea Electronics (DSE) +Each generator has the same controller/interface, the Deep Sea Electronics (DSE) 8610 mark II. The Generator Agent allows the monitoring of each generator controller via Modbus. It queries registers and publishes data in an acquisition process. The agent has been tested with on-site generators. -The Generator Agent requires a config file which contains information on all -possible registers that it may query from the generator controller. The config file -also sets the amount of registers we want to query in the acquisition process. +The Generator Agent requires a configuration directory which contains information on all +registers that it queries from the generator controller. Agent Fields ```````````` - The fields consist of the register name and the last value, which are necessarily formatted depending on the register. +Configuration +````````````` +A direcotry of .yaml configuration files is one of the arguments to the agent. +A single .yaml file specifies meta-data about a continuous block of registers to +read. The agent will interpret all .yaml files in the specified directory as +specifications of register blocks. + +A single .yaml file must contain keys that specify which registers to read and +how to interpret the data contained in those registers. The key 'read_start' or +'page' must be specified, where 'read_start' is the register offset to begin reading +at, and 'page' is a shorthand for read_start = 256 * page because the DSE GenComm +documentation lists all registers as an offset from their page number. If both keys +are specified, 'read_start' is given preference. + +The configuration file must also specify 'read_len', which is how many registers to read +beyond the 'read_start' value. + +The 'registers' key contains a dictionary with information about how to interpret the data +contained in the registers that are read. There is no requirement to read all registers +returned in the block, and the same registers can be interpreted by multiple entries in +the 'registers' key. + +An example 'registers' entry is contained below:: + + Engine_fuel_level: + max_val: 130.0 + min_val: 0.0 + offset: 3 + read_as: 16U + scale: 1.0 + units: '%' + +They key for each register entry is a description of what information the register contains. +The sub-keys 'offset', 'read_as', 'scale', and 'units' are required entries, but 'max_val' and +'min_val' are optional. + +read_as must be one of 16U, 16S, 32U, 32S, or bin. These specify how the data in the register +contained at the specified offset should be interpereted: 16 bit unsigned (16U), 16 bit signed (16S), +32 bit unsigned (32U), 32 bit signed (32S) or binary (bin). When the 32 bit data types are used, it is +implied that the register one byond the specified offset is also being read because each register is +only 16 bits long. In this case binary corresponds to reading a value from an individual bit or range of +bits within a single 16 bit register. A single bit can be read by specifying i.e. 'bin 2' which would +correspond to reading the second most significant bit out of the register, and a range can be specified +by i.e. 'bin 5-8'. The values specified by 'bin' are one-indexed, following the GenComm documentation +specifications. An example of reading different binary values out of the same register follows:: + + Alarm_emergency_stop: + offset: 1 + read_as: bin 13-16 + units: None + Alarm_low_oil_pressure: + offset: 1 + read_as: bin 9-12 + units: None + +Finally, the file must specify the 'block_name' key which is a description of what the continuous +block of registers contains. + Agent API --------- diff --git a/socs/agents/generator/agent.py b/socs/agents/generator/agent.py index 011fe2f62..3f4296a3d 100644 --- a/socs/agents/generator/agent.py +++ b/socs/agents/generator/agent.py @@ -12,39 +12,108 @@ byteorder = sys.byteorder +def load_configs(dir_name, config_extension='yaml'): + '''Loads all register configuration files form the specified directory (path). + The configurations are returned as a list of the configurations from individual files.''' + + config_dir = os.environ.get('OCS_CONFIG_DIR') + path = os.path.join(config_dir, 'generator_config', dir_name) + + all_configs = [] + + ls = os.listdir(path) + + # Make a filter so that we only try to load files ending in config_extension + def filt(f_name): + return f_name.endswith(config_extension) + # Filter + configs = filter(filt, ls) + # Load configurations from the remaining files + for f in configs: + read_config = os.path.join(path, f) + with open(read_config) as f: + try: + data = yaml.load(f, Loader=yaml.SafeLoader) + except BaseException: + pass + all_configs.append(data) + return all_configs + + def twos(val, bytes): - """Take an unsigned integer representation of a two's compilment integer - and return the correctly signed integer""" + '''Take an unsigned integer representation of a two's compilment integer and return the correctly signed integer''' b = val.to_bytes(bytes, byteorder=byteorder, signed=False) return int.from_bytes(b, byteorder=byteorder, signed=True) def interp_unsigned_double_reg(r1, r2): - """Take two 16 bit register values and combine them assuming we really - wanted to read a 32 bit unsigned register""" + '''Take two 16 bit register values and combine them assuming we really wanted to read a 32 bit unsigned register''' return (r1 << 16) + r2 def interp_signed_double_reg(r1, r2): - """Take two 16 bit register values and combine them assuming we really - wanted to read a 32 bit signed register""" + '''Take two 16 bit register values and combine them assuming we really wanted to read a 32 bit signed register''' return twos(interp_unsigned_double_reg(r1, r2), 4) -class ReadString(object): +def make_bin_reader(offset, spec): + '''Read an individual bit or continuous range of bits out of the 2 byte register. + A single bit can be specified as a single number between 1 and 16, and a range can + be specified with a dash, i.e. X-Y where both X and Y are in the range + 1 to 16 and X < Y. In either case the bit or range of bits will be returned as an + integer.''' + spec = spec.split(' ')[1:] + spec = spec[0].split('-') + spec = [int(s) for s in spec] + if len(spec) == 1: + # Process individual bit + spec = spec[0] + # The mask leaves only the desired bit + mask = sum([1 << s for s in range(spec - 1, spec)]) + + def reader(val): + return (val[offset] & mask) >> spec - 1 + return reader + elif len(spec) == 2: + # Process range + low = spec[0] + high = spec[1] + if low >= high: + raise ValueError('First bit in range specification must be smaller than last.') + # The mask leaves only the desired bits + mask = sum([1 << s for s in range(low - 1, high)]) + + def reader(val): + return (val[offset] & mask) >> low - 1 + return reader + else: + raise ValueError('Cannot read binary read_as specification; use single bit or continuous range.') + + +class ReadBlock(object): + '''An object for reading, converting, and evaluating information from a single contiouous block of registers''' + + def __init__(self, config, error_out_of_range=True, filter_errors=True): + self.name = config['block_name'] + + try: + self.read_start = config['read_start'] + except KeyError: + self.read_start = config['page'] * 256 - def __init__(self, config, error_out_of_range=True): - self.name = config['string_name'] - self.read_start = config['read_start'] self.read_len = config['read_len'] self.functions = [] self.rconfig = config['registers'] - self.error_val = -1 + self.error_val = None self.error_out_of_range = error_out_of_range + self.filter_errors = filter_errors for i in self.rconfig: self.functions.append(self.build_reader_function(i, self.rconfig[i])) - def build_reader_function(self, offset, rconfig): + def build_reader_function(self, name, rconfig): + '''Build and return a closure around a function that converts a specified piece of information from the block''' + offset = rconfig['offset'] + if rconfig['read_as'] == '16U': def evaluator(registers): return registers[offset] @@ -57,6 +126,8 @@ def evaluator(registers): elif rconfig['read_as'] == '32S': def evaluator(registers): return interp_signed_double_reg(registers[offset], registers[offset + 1]) + elif 'bin' in rconfig['read_as']: + evaluator = make_bin_reader(offset, rconfig['read_as']) else: def evaluator(registers): return self.error_val @@ -68,7 +139,7 @@ def process(registers): if self.error_out_of_range: try: - if val < rconfig['min_va']: + if val < rconfig['min_val']: val = self.error_val except KeyError: pass @@ -79,18 +150,26 @@ def process(registers): except KeyError: pass - return {rconfig['name'].replace(' ', '_'): {'value': val, 'units': rconfig['units']}} + if val != self.error_val or not self.filter_errors: + return {name: {'value': float(val), 'units': rconfig['units']}} + else: + return None return process def read(self, client): - regdata = client.read_holding_registers(self.read_start, self.read_len) - regs = regdata + # Perform the read for the entire block + registers = client.read_holding_registers(self.read_start, self.read_len) return_data = {} try: - for i in range(self.read_len): - return_data.update(self.functions[i](regs)) + # Iterate through the functions that convert and return the individual pieces of + # data from this block + for f in self.functions: + this_data = f(registers) + if this_data is not None: + return_data.update(this_data) except Exception as e: + # print(registers) print(f'Error in processing data: {e}') return return_data @@ -105,44 +184,62 @@ class Generator: Address of the generator controller. port : int Port to generator controller, default to 5021. + config_dir : string + Sub-directory of .yaml configuration files that specify blocks of registers to read + and specifies how to convert them into useable data. + block_space_time : float + Amount of time (in seconds) to wait between issuing seperate read_multiple_registers + commands to the device. DSE device appears to crash without this waiting period. + close_port : boolean + Whether or not to close the open port to the device while waiting for the next Pacemaker + triggered read cycle. The idea here is that closing the port alllows DSEWebNet to function + in parallel with the agent. Attributes ---------- - read_strings : list - Strings of registers defined in config to read from + read_blocks : list + List of ReadBlock objects that represent the different continuous register locations to + read from as specified in the config files. client : ModbusClient ModbusClient object that initializes connection """ - def __init__(self, host, port): + def __init__(self, host, port, config_dir, block_space_time=.1, close_port=True): self.host = host self.port = port - self.read_strings = [] - + self.read_config = load_configs(config_dir) self._build_config() - + self.close_port = close_port + self.block_space_time = block_space_time self.client = ModbusClient(self.host, self.port, auto_open=True, auto_close=False) self.client.open() def _build_config(self): - read_config = os.path.join(os.path.dirname(__file__), "config.yaml") - with open(read_config) as f: - data = yaml.load(f, Loader=yaml.SafeLoader) - for string in [data]: - self.read_strings.append(ReadString(string)) + self.read_blocks = [] + for block in self.read_config: + self.read_blocks.append(ReadBlock(block)) def read_cycle(self): - for i, val in enumerate(self.read_strings): + this_cycle_data = {} + for i, val in enumerate(self.read_blocks): data = self._read_regs(val) - return data - - def _read_regs(self, register_string_obj): + this_cycle_data.update(data) + time.sleep(self.block_space_time) # A gap in time is required between individual requests, + # i.e. a pause between reading each read_multiple_registers command. + return this_cycle_data + + def _read_regs(self, register_block_object): + if self.close_port: + self.client.open() try: - data = register_string_obj.read(self.client) + data = register_block_object.read(self.client) except Exception as e: print('error in read', e) + if self.close_port: + self.client.open() return - + if self.close_port: + self.client.open() return data @@ -153,10 +250,15 @@ class GeneratorAgent: ---------- agent : OCSAgent OCSAgent object which forms this Agent + configdir : str + Directory where .yaml configuration files specific to this generator instance + are stored. host : str Address of the generator controller. port : int Port to generator controller, default to 5021. + sample_interval : float + Time between samples in seconds. Attributes ---------- @@ -169,7 +271,7 @@ class GeneratorAgent: txaio logger object, created by the OCSAgent """ - def __init__(self, agent, host='localhost', port=5021): + def __init__(self, agent, configdir, host='localhost', port=5021, sample_interval=10.): self.host = host self.port = port @@ -178,6 +280,10 @@ def __init__(self, agent, host='localhost', port=5021): self.log = agent.log self.lock = TimeoutLock() + self.configdir = configdir + + self.pacemaker_freq = 1. / sample_interval + self.initialized = False self.take_data = False @@ -196,7 +302,7 @@ def _connect(self): Instantiates Generator object and check if client is open """ - self.generator = Generator(self.host, self.port) + self.generator = Generator(self.host, self.port, config_dir=self.configdir) if self.generator.client.is_open: self.initialized = True else: @@ -261,11 +367,6 @@ def acq(self, session, params=None): "address": 'localhost', "timestamp":1601925677.6914878} - Refer to the config file at `socs/agents/generator/config.yaml`_ - for all possible fields and their respective min/max values and units. - Note: -1 will be returned for readings out of range. - - .. _socs/agents/generator/config.yaml: https://github.com/simonsobs/socs/blob/main/socs/agents/generator/config.yaml """ @@ -281,7 +382,7 @@ def acq(self, session, params=None): session.data = {"fields": {}} - pm = Pacemaker(1, quantize=True) + pm = Pacemaker(self.pacemaker_freq) while self.take_data: pm.sleep() @@ -306,11 +407,10 @@ def acq(self, session, params=None): session.data['address'] = self.host regdata = self.generator.read_cycle() - if regdata: for reg in regdata: data['data'][reg] = regdata[reg]["value"] - field_dict = {reg: regdata[reg]} + field_dict = {reg: regdata[reg]['value']} session.data['fields'].update(field_dict) session.data.update({'timestamp': current_time}) else: @@ -351,6 +451,8 @@ def make_parser(parser=None): help="Port to listen on.") pgroup.add_argument('--mode', type=str, choices=['idle', 'init', 'acq'], help="Starting action for the agent.") + pgroup.add_argument("--configdir", type=str, help="Path to directory containing .yaml config files.") + pgroup.add_argument("--sample-interval", type=float, default=10., help="Time between samples in seconds.") return parser @@ -376,8 +478,10 @@ def main(args=None): agent, runner = ocs_agent.init_site_agent(args) p = GeneratorAgent(agent, + configdir=args.configdir, host=args.host, - port=int(args.port)) + port=int(args.port), + sample_interval=args.sample_interval) agent.register_task('init_generator', p.init_generator, startup=init_params) diff --git a/socs/agents/generator/config.yaml b/socs/agents/generator/config.yaml deleted file mode 100644 index c89f5e64c..000000000 --- a/socs/agents/generator/config.yaml +++ /dev/null @@ -1,396 +0,0 @@ -read_len: 8 # update this to number of registers to query starting from 0 -read_start: 1024 -registers: - 0: - max_val: 10000.0 - min_val: 0.0 - name: Oil pressure - read_as: 16U - scale: 1.0 - units: Kpa - 1: - max_val: 200.0 - min_val: -50.0 - name: Coolant temperature - read_as: 16S - scale: 1.0 - units: Degrees C - 2: - max_val: 200.0 - min_val: -50.0 - name: Oil temperature - read_as: 16S - scale: 1.0 - units: Degrees C - 3: - max_val: 130.0 - min_val: 0.0 - name: Fuel level - read_as: 16U - scale: 1.0 - units: '%' - 4: - max_val: 40.0 - min_val: 0.0 - name: Charge alternator voltage - read_as: 16U - scale: 0.1 - units: V - 5: - max_val: 40.0 - min_val: 0.0 - name: Engine Battery voltage - read_as: 16U - scale: 0.1 - units: V - 6: - max_val: 6000.0 - min_val: 0.0 - name: Engine speed - read_as: 16U - scale: 1.0 - units: RPM - 7: - max_val: 70.0 - min_val: 0.0 - name: Generator frequency - read_as: 16U - scale: 0.1 - units: Hz - 8: - max_val: 18000.0 - min_val: 0.0 - name: Generator L1-N voltage - read_as: 32U - scale: 0.1 - units: V - 10: - max_val: 18000.0 - min_val: 0.0 - name: Generator L2-N voltage - read_as: 32U - scale: 0.1 - units: V - 12: - max_val: 18000.0 - min_val: 0.0 - name: Generator L3-N voltage - read_as: 32U - scale: 0.1 - units: V - 14: - max_val: 30000.0 - min_val: 0.0 - name: Generator L1-L2 voltage - read_as: 32U - scale: 0.1 - units: V - 16: - max_val: 30000.0 - min_val: 0.0 - name: Generator L2-L3 voltage - read_as: 32U - scale: 0.1 - units: V - 18: - max_val: 30000.0 - min_val: 0.0 - name: Generator L3-L1 voltage - read_as: 32U - scale: 0.1 - units: V - 20: - max_val: 99999.9 - min_val: 0.0 - name: Generator L1 current - read_as: 32U - scale: 0.1 - units: A - 22: - max_val: 99999.9 - min_val: 0.0 - name: Generator L2 current - read_as: 32U - scale: 0.1 - units: A - 24: - max_val: 99999.9 - min_val: 0.0 - name: Generator L3 current - read_as: 32U - scale: 0.1 - units: A - 26: - max_val: 99999.9 - min_val: 0.0 - name: Generator earth current - read_as: 32U - scale: 0.1 - units: A - 28: - max_val: 99999999.0 - min_val: -99999999.0 - name: Generator L1 watts - read_as: 32S - scale: 1.0 - units: W - 30: - max_val: 99999999.0 - min_val: -99999999.0 - name: Generator L2 watts - read_as: 32S - scale: 1.0 - units: W - 32: - max_val: 99999999.0 - min_val: -99999999.0 - name: Generator L3 watts - read_as: 32S - scale: 1.0 - units: W - 34: - max_val: 180.0 - min_val: -180.0 - name: Generator current lag/lead - read_as: 16S - scale: 1.0 - units: degrees - 35: - max_val: 70.0 - min_val: 0.0 - name: Mains frequency - read_as: 16U - scale: 0.1 - units: Hz - 36: - max_val: 18000.0 - min_val: 0.0 - name: Mains L1-N voltage - read_as: 32U - scale: 0.1 - units: V - 38: - max_val: 18000.0 - min_val: 0.0 - name: Mains L2-N voltage - read_as: 32U - scale: 0.1 - units: V - 40: - max_val: 18000.0 - min_val: 0.0 - name: Mains L3-N voltage - read_as: 32U - scale: 0.1 - units: V - 42: - max_val: 30000.0 - min_val: 0.0 - name: Mains L1-L2 voltage - read_as: 32U - scale: 0.1 - units: V - 44: - max_val: 30000.0 - min_val: 0.0 - name: Mains L2-L3 voltage - read_as: 32U - scale: 0.1 - units: V - 46: - max_val: 30000.0 - min_val: 0.0 - name: Mains L3-L1 voltage - read_as: 32U - scale: 0.1 - units: V - 48: - max_val: 180.0 - min_val: -180.0 - name: Mains voltage phase lag/lead - read_as: 16S - scale: 1.0 - units: degrees - 49: - max_val: 3.0 - min_val: 0.0 - name: Generator phase rotation - read_as: 16U - scale: 1.0 - units: '' - 50: - max_val: 3.0 - min_val: 0.0 - name: Mains phase rotation - read_as: 16U - scale: 1.0 - units: '' - 51: - max_val: 180.0 - min_val: -180.0 - name: Mains current lag/lead - read_as: 16S - scale: 1.0 - units: degrees - 52: - max_val: 99999.9 - min_val: 0.0 - name: Mains L1 current - read_as: 32U - scale: 0.1 - units: A - 54: - max_val: 99999.9 - min_val: 0.0 - name: Mains L2 current - read_as: 32U - scale: 0.1 - units: A - 56: - max_val: 99999.9 - min_val: 0.0 - name: Mains L3 current - read_as: 32U - scale: 0.1 - units: A - 58: - max_val: 99999.9 - min_val: 0.0 - name: Mains earth current - read_as: 32U - scale: 0.1 - units: A - 60: - max_val: 99999999.0 - min_val: -99999999.0 - name: Mains L1 watts - read_as: 32S - scale: 1.0 - units: W - 62: - max_val: 99999999.0 - min_val: -99999999.0 - name: Mains L2 watts - read_as: 32S - scale: 1.0 - units: W - 64: - max_val: 99999999.0 - min_val: -99999999.0 - name: Mains L3 watts - read_as: 32S - scale: 1.0 - units: W - 66: - max_val: 180.0 - min_val: -180.0 - name: Bus current lag/lead - read_as: 16S - scale: 1.0 - units: degrees - 67: - max_val: 70.0 - min_val: 0.0 - name: Bus frequency - read_as: 16U - scale: 0.1 - units: Hz - 68: - max_val: 18000.0 - min_val: 0.0 - name: Bus L1-N voltage - read_as: 32U - scale: 0.1 - units: V - 70: - max_val: 18000.0 - min_val: 0.0 - name: Bus L2-N voltage - read_as: 32U - scale: 0.1 - units: V - 72: - max_val: 18000.0 - min_val: 0.0 - name: Bus L3-N voltage - read_as: 32U - scale: 0.1 - units: V - 74: - max_val: 30000.0 - min_val: 0.0 - name: Bus L1-L2 voltage - read_as: 32U - scale: 0.1 - units: V - 76: - max_val: 30000.0 - min_val: 0.0 - name: Bus L2-L3 voltage - read_as: 32U - scale: 0.1 - units: V - 78: - max_val: 30000.0 - min_val: 0.0 - name: Bus L3-L1 voltage - read_as: 32U - scale: 0.1 - units: V - 80: - max_val: 99999.9 - min_val: 0.0 - name: Bus L1 current - read_as: 32U - scale: 0.1 - units: A - 82: - max_val: 99999.9 - min_val: 0.0 - name: Bus L2 current - read_as: 32U - scale: 0.1 - units: A - 84: - max_val: 99999.9 - min_val: 0.0 - name: Bus L3 current - read_as: 32U - scale: 0.1 - units: A - 86: - max_val: 99999.9 - min_val: 0.0 - name: Bus earth current - read_as: 32U - scale: 0.1 - units: A - 88: - max_val: 999999999.0 - min_val: -999999999.0 - name: Bus L1 watts - read_as: 32S - scale: 1.0 - units: W - 90: - max_val: 999999999.0 - min_val: -999999999.0 - name: Bus L2 watts - read_as: 32S - scale: 1.0 - units: W - 92: - max_val: 999999999.0 - min_val: -999999999.0 - name: Bus L3 watts - read_as: 32S - scale: 1.0 - units: W - 94: - max_val: 3.0 - min_val: 0.0 - name: Bus phase rotation - read_as: 16U - scale: 1.0 - units: '' -string_name: Engine Data diff --git a/socs/agents/generator/sample_configs/Alarms.yaml b/socs/agents/generator/sample_configs/Alarms.yaml new file mode 100644 index 000000000..ef1ff5df6 --- /dev/null +++ b/socs/agents/generator/sample_configs/Alarms.yaml @@ -0,0 +1,121 @@ +read_len: 17 +page: 154 +registers: + Alarm_emergency_stop: + offset: 1 + read_as: bin 13-16 + units: None + Alarm_low_oil_pressure: + offset: 1 + read_as: bin 9-12 + units: None + Alarm_high_coolant_temperature: + offset: 1 + read_as: bin 5-8 + units: None + Alarm_low_coolant_temperature: + offset: 1 + read_as: bin 1-4 + units: None + Alarm_under_speed: + offset: 2 + read_as: bin 13-16 + units: None + Alarm_over_speed: + offset: 2 + read_as: bin 9-12 + units: None + Alarm_generator_under_frequency: + offset: 2 + read_as: bin 5-8 + units: None + Alarm_generator_over_frequency: + offset: 2 + read_as: bin 1-4 + units: None + Alarm_generator_low_voltage: + offset: 3 + read_as: bin 13-16 + units: None + Alarm_generator_high_voltage: + offset: 3 + read_as: bin 9-12 + units: None + Alarm_battery_low_voltage: + offset: 3 + read_as: bin 5-8 + units: None + Alarm_battery_high_voltage: + offset: 3 + read_as: bin 1-4 + units: None + Alarm_charge_alternator_failure: + offset: 4 + read_as: bin 13-16 + units: None + Alarm_generator_fail_to_start: + offset: 4 + read_as: bin 9-12 + units: None + Alarm_generator_fail_to_stop: + offset: 4 + read_as: bin 5-8 + units: None + Alarm_generator_fail_to_close: + offset: 4 + read_as: bin 1-4 + units: None + Alarm_oil_pressure_sender: + offset: 5 + read_as: bin 9-12 + units: None + Alarm_loss_of_magnetic_pick_up: + offset: 5 + read_as: bin 5-8 + units: None + Alarm_magnetic_pick_up_open_circuit: + offset: 5 + read_as: bin 1-4 + units: None + Alarm_generator_high_current: + offset: 6 + read_as: bin 13-16 + units: None + Alarm_low_fuel_level: + offset: 6 + read_as: bin 5-8 + units: None + Alarm_CAN_ECU_Warning: + offset: 6 + read_as: bin 1-4 + units: None + Alarm_CAN_ECU_Shutdown: + offset: 7 + read_as: bin 13-16 + units: None + Alarm_CAN_ECU_data_fail: + offset: 7 + read_as: bin 9-12 + units: None + Alarm_low_oil_level_switch: + offset: 7 + read_as: bin 5-8 + units: None + Alarm_high_temperature_switch: + offset: 7 + read_as: bin 1-4 + units: None + Alarm_low_fuel_level_switch: + offset: 8 + read_as: bin 13-16 + units: None + Alarm_MSC_data_error: + offset: 14 + read_as: bin 5-8 + units: None + Alarm_MSC_failure: + offset: 16 + read_as: bin 13-16 + units: None + +block_name: Alarms diff --git a/socs/agents/generator/sample_configs/Engine_Data.yaml b/socs/agents/generator/sample_configs/Engine_Data.yaml new file mode 100644 index 000000000..3144a9e1d --- /dev/null +++ b/socs/agents/generator/sample_configs/Engine_Data.yaml @@ -0,0 +1,193 @@ +read_len: 94 +read_start: 1024 +registers: + Engine_oil_pressure: + max_val: 10000.0 + min_val: 0.0 + offset: 0 + read_as: 16U + scale: 1.0 + units: Kpa + Engine_coolant_temperature: + max_val: 200.0 + min_val: -50.0 + read_as: 16S + offset: 1 + scale: 1.0 + units: Degrees C + Engine_oil_temperature: + max_val: 200.0 + min_val: -50.0 + read_as: 16S + offset: 2 + scale: 1.0 + units: Degrees C + Engine_fuel_level: + max_val: 130.0 + min_val: 0.0 + offset: 3 + read_as: 16U + scale: 1.0 + units: '%' + Engine_battery_voltage: + max_val: 40.0 + min_val: 0.0 + offset: 5 + read_as: 16U + scale: 0.1 + units: V + Engine_speed: + max_val: 6000.0 + min_val: 0.0 + offset: 6 + read_as: 16U + scale: 1.0 + units: RPM + Generator_frequency: + max_val: 70.0 + min_val: 0.0 + offset: 7 + read_as: 16U + scale: 0.1 + units: Hz + Generator_L1_N_voltage: + max_val: 18000.0 + min_val: 0.0 + offset: 8 + read_as: 32U + scale: 0.1 + units: V + Generator_L2_N_voltage: + max_val: 18000.0 + min_val: 0.0 + offset: 10 + read_as: 32U + scale: 0.1 + units: V + Generator_L3_N_voltage: + max_val: 18000.0 + min_val: 0.0 + read_as: 32U + offset: 12 + scale: 0.1 + units: V + Generator_L1_L2_voltage: + max_val: 30000.0 + min_val: 0.0 + offset: 14 + read_as: 32U + scale: 0.1 + units: V + Generator_L2_L3_voltage: + max_val: 30000.0 + min_val: 0.0 + offset: 16 + read_as: 32U + scale: 0.1 + units: V + Generator_L3_L1_voltage: + max_val: 30000.0 + min_val: 0.0 + offset: 18 + read_as: 32U + scale: 0.1 + units: V + Generator_L1_current: + max_val: 99999.9 + min_val: 0.0 + offset: 20 + read_as: 32U + scale: 0.1 + units: A + Generator_L2_current: + max_val: 99999.9 + min_val: 0.0 + offset: 22 + read_as: 32U + scale: 0.1 + units: A + Generator_L3_current: + max_val: 99999.9 + min_val: 0.0 + offset: 24 + read_as: 32U + scale: 0.1 + units: A + Generator_earth_current: + max_val: 99999.9 + min_val: 0.0 + offset: 26 + read_as: 32U + scale: 0.1 + units: A + Generator_L1_watts: + max_val: 99999999.0 + min_val: -99999999.0 + offset: 28 + read_as: 32S + scale: 1.0 + units: W + Generator_L2_watts: + max_val: 99999999.0 + min_val: -99999999.0 + offset: 30 + read_as: 32S + scale: 1.0 + units: W + Generator_L3_watts: + max_val: 99999999.0 + min_val: -99999999.0 + offset: 32 + read_as: 32S + scale: 1.0 + units: W + Bus_frequency: + max_val: 70.0 + min_val: 0.0 + offset: 67 + read_as: 16U + scale: 0.1 + units: Hz + Bus_L1_N_voltage: + max_val: 18000.0 + min_val: 0.0 + offset: 68 + read_as: 32U + scale: 0.1 + units: V + Bus_L2_N_voltage: + max_val: 18000.0 + min_val: 0.0 + offset: 70 + read_as: 32U + scale: 0.1 + units: V + Bus_L3_N_voltage: + max_val: 18000.0 + min_val: 0.0 + read_as: 32U + offset: 72 + scale: 0.1 + units: V + Bus_L1_L2_voltage: + max_val: 30000.0 + min_val: 0.0 + offset: 74 + read_as: 32U + scale: 0.1 + units: V + Bus_L2_L3_voltage: + max_val: 30000.0 + min_val: 0.0 + offset: 76 + read_as: 32U + scale: 0.1 + units: V + Bus_L3_L1_voltage: + max_val: 30000.0 + min_val: 0.0 + offset: 78 + read_as: 32U + scale: 0.1 + units: V +block_name: Engine Data