The Inventory

Introduction

In true Student Robotics fashion, the inventory is a Git repository containing YAML files tied together with Python scripts.

All items owned by Student Robotics, except those of very low-value, are tracked in this system. The main purpose of this is to allow us to know what we have, where it is and what condition it is in.

There is an API for talking with the inventory from Python and also an extensive query language.

Actions

Creation of Assets

Assets should be created with the inv-new-asset command. This command takes a single argument which is the name of the asset (i.e. motor-board). The new asset is created by copying a template with the name of the asset from the .meta/parts dir in the inventory repository. If the template does not exist the template default will be used.

The inv-new-asset command will generate a new unique asset code and use this to both name the file and set the assetcode field in the file. To create the unique asset code the command requires the user to have a record in the .meta/users file, this is to ensure there are not collisions between asset codes. The name looked up in the users file is the git name/email of the user and the number assigned to a name must be unique. When adding yourself to the users file please take care to ensure that you do not end up with the same ID number as another user.

Creation of Assemblies

Assemblies are groups of assets which have their own asset code allowing for the grouping of assets to be tracked over time. An example of an assembly is a power board which consists of: case, power board, BeagleBoard, LCD. Assemblies are represented as directories in the inventory repository. A directory is an assembly if its name includes an asset code and there is a file called info in the directory. The info file allows for a description of the assembly to be stored along with a revision number which allows for log messages to be recorded about the assembly.

Assemblies can be created in one of two ways. An assembly directory can be created from scratch with the sr inv-new-group command. This will create the directory and also the associated info file. As with the creation of assets this command will look for templates for the info file in .meta/assemblies. If a directory already exists then this can be promoted to an assembly by running the inv-new-group command on it. This will append an asset code and create the info file.

Creating Assemblies and Assets at the same time

The process of creating assets, then creating an assembly and placing them in it, is modelled on SRs production process: we manufacture individual pieces of kit and then combine them into assemblies. However, at the end of SR2011 we have a large set of kits that are assembled but not in the inventory at all. It is therefore convenient to have a method of creating both an assembly and it’s assets at the same time, to help putting SR2011s kit into the inventory. This is achieved with the --all option to sr inv-new-group.

Movement of Assets

When an asset is moved from one location to another, e.g. from a persons house to the vault, the file representing it is moved in the inventory repository accordingly. When an asset is in the possession of an individual it is up to that individual as to how detailed they track the movements of the asset. If they move it between various locations while it is in their possession then they are not obliged to detail this in the inventory system, however they are responsible for its safekeeping.

Logging of Non-state Information

It will occasionally be necessary to detail information about an asset that is not purely conveyed by the state stored in its file. In this case detailed information can be recorded in a commit message associated with the asset file. To enable a commit to be made, and associated with a specific file, each asset file contains a revision number field which can be incremented. This field means that non-null commits can be made. Incrementing that field can be achieved by using the inv-touch command.

Making Queries

Currently, there are 3 types of expressions: equality/match, membership and function. The equality/match expression takes the form KEY (':' | '=' | 'is') VALUE. The membership expression takes the form KEY 'in' '{' VALUE (',' VALUE)* '}'. The function expression takes the form FUNCTION 'of' EXPR, where EXPR is another valid expression.

Supported keys

Code

Match on a part code.

Keys:code
Values:a valid SR part code, with or without the sr prefix
Example:code:srEEN
Serial

Match on a serial number.

Keys:serial
Values:a valid serial number
Example:serial:D851F850
Condition

Match on the condition of a part/assembly. An assembly is considered working if and only if all expected sub-parts are considered working. If any sub-part is broken or missing, the assembly is broken. If any sub-part is unknown and the assembly is not broken then the assembly is unknown.

Keys:condition, cond
Values:working, unknown, broken
Example:condition is working
Labelled

Match based on how labelled a part is.

Keys:labelled
Values:true, false
Example:labelled=true
Type or name of part

Match on the name of a part/assembly. Python’s fnmatch is used, and it uses glob-like syntax. Basic usage: ‘*’ matches any character, any number of times; ? matches a single character; [ab] matches one of the characters a or b.

Keys:type
Values:a glob-like pattern
Examples:type:power*, for all parts whose name begins with ‘power’
Path

Match on the path to the part in the inventory. Python’s fnmatch is used here too, but with an implicit * at the end. This makes path searching more intuitive.

Keys:path
Values:a valid glob-like pattern
Example:path:vault, for all parts under any path, relative to the inventory root, that begins with ‘vault
Assembly

Match based on whether a part/assembly is an assembly or not.

Keys:assy
Values:true, false
Example:assy:true

Logic

AND, OR, and NOT are all supported. NOT may be abreviated to !. When two expressions appear side-by-side with no operator (AND, or OR) between them, AND is assumed, e.g. a b is equivalent to a AND b. These keywords are not case insensitive.

One may also use parenthetic expressions.

Function Expressions

Function expressions currently allow one to map the list of matches (from the input expression) using some named function. The current functions are: parent, siblings, children, and descendants. For example, parent of type:power-board-sr13.f will return the parent nodes of sr13 power boards. (Note that this particular example doesn’t guarantee the parents are assemblies, they could be boxes for example. One can fix this by adding assy:true.) Function expressions bind tighter than AND, so parent of type:power-board-sr13.f AND assy:true, with parentheses for clarity, means (parent of type:power-board-sr13.f) AND assy:true.

Examples

  • cond:working - returns all working parts and assemblies.
  • type is *power* - returns parts that match that glob pattern (power boards and assys, power supplies, etc…).
  • !path:vault - returns items not under paths starting with vault.
  • path:vault !cond:working - returns the things in the vault that are not working (note the implicit AND).
  • cond:working AND (path:bees OR path:face) - returns working things in bees* or in face*. This could be simplified with the membership syntax: cond:working AND path in {bees*, face*}
  • type in {motor-board-sr11.f, motor-board-sr13.f} - returns all of our motor boards. In this case, a glob pattern could be used to shorten it: type:motor-board-sr1[13].f.
  • descendants of code:srBOX and cond:broken - return all the broken things in srBOX.
  • siblings of code:srABC - things at the same level in the hierarchy as srABC.

Users

New Users

Before creating or editing assets, you need to record information about yourself in the inventory. In the file .meta/users, observe a list of users containing name, email addresse and a unique number. Append your own information to this list, with the next sequential number following the last list enry, and using the same email address as for your git commits.

You must ensure that you get this change pushed to the master inventory repository, inventory.git, before creating any assets/assemblies. The users file is the only part of the system that isn’t safe with distributed editing; if two people add themselves to the users file and create assets without first getting the users file change pushed things will not end well.

Labelling Assets

All assets that are entered into the inventory system must have their asset code written on them. When first entering items into the inventory it is possible to indicate that an asset does not yet have its code written on with the labelled field however the code should be written on as soon as possible and the inventory updated as appropriate. Only asset codes assigned to actually assets should be written onto items, not asset codes assigned to assemblies. An asset code assigned to an assembly is used as a unique identifier in the inventory system and it does not make sense to write it onto any real-world item.

Technical Details

Asset File Format

Each asset is stored as a file with a filename in the form of ‘name-assetcode’ where ‘name’ is the name of the asset e.g. ‘battery-charger’ and ‘assetcode’ is a unique code which can be written on the asset to allow it to be tracked. Each file is written in YAML and contains information about the asset in pre-defined fields.

Asset File Fields

A definitive list of file fields can be found in the default template located in the inventory git repository (.meta/parts/default).