canlink
index
/home/pfeiffer/project-shared/publicize/bii_scripts-top/bii_scripts/lib/python/bii_scripts/canlink.py

canlink - a module for the encoding and decoding the MultiCAN CAN Link. 
 
This module contains functions to decode and encode the EPICS hardware link
definition that is used in MultiCAN. The EPICS device and driver support for
the CAN bus that was developed for the BESSY II control system.

 
Modules
       
sys

 
Functions
       
calc_cidnidsob(p)
tries to calc cid,nid or cid,[in/out]_sob from in_cob and out_cob.
 
parameters:
    p    - the property dictionary
 
returns:
    nothing
 
This function *modifies* the given dictionary. It adds the fields "cid" and
"nid" or "cid" and "in_sob" and "out_sob". The values of these fields are
calculated from the fields "in_cob" and "out_cob". The field "in_sob" is
only set if the described CAN variable needs an input CAN object, the field
"out_sob" is only set if the CAN variable needs an output CAN object.
 
Here are some examples:
 
>>> def t(multi, access, server, in_cob, out_cob):
...     d={"multi":multi, "access":access, "server":server}
...     if in_cob is not None:
...         d["in_cob"]= in_cob
...     if out_cob is not None:
...         d["out_cob"]= out_cob
...     calc_cidnidsob(d)
...     print "nid: %s  cid: %s  in_sob: %s  out_sob: %s" %                   (d.get("nid"), d.get("cid"), d.get("in_sob"), d.get("out_sob"))
 
>>> t(False, "r", False, 1157, None)
nid: 5  cid: 9  in_sob: 18  out_sob: None
>>> t(False, "w", False, None, 1221)
nid: 5  cid: 9  in_sob: None  out_sob: 19
>>> t(False, "rw", False, 1157, 1221)
nid: 5  cid: 9  in_sob: 18  out_sob: 19
>>> t(False, "r", True, None, 1221)
nid: 5  cid: None  in_sob: None  out_sob: 19
>>> t(False, "w", True, 1157, None)
nid: 5  cid: None  in_sob: 18  out_sob: None
>>> t(False, "rw", True, 1157, 1221)
nid: 5  cid: 9  in_sob: 18  out_sob: 19
>>> t(True, "r", False, 1157, 1221)
nid: 5  cid: 9  in_sob: 18  out_sob: 19
>>> t(True, "w", False, None, 1221)
nid: 5  cid: 9  in_sob: None  out_sob: 19
>>> t(True, "rw", False, 1157, 1221)
nid: 5  cid: 9  in_sob: 18  out_sob: 19
>>> t(False, "rw", False, 709, 837)
nid: 5  cid: None  in_sob: 11  out_sob: 13
>>> t(False, "r", False, 709, None)
nid: 5  cid: None  in_sob: 11  out_sob: None
>>> t(False, "w", False, None, 837)
nid: 5  cid: 6  in_sob: None  out_sob: 13
>>> t(False, "rw", True, 12, 34)
nid: None  cid: None  in_sob: None  out_sob: None
calc_cob(p)
calculates and sets "in_cob" and "out_cob" in the property dictionary.
 
calculates in_cob and out_cob from nid and cid or nid and in_sob and
out_sob.
 
parameters:
    p    - the property dictionary
 
returns:
    nothing
 
This function *modifies* the given dictionary. It adds the fields "in_cob"
and "out_cob". The values of these fields are calculated from the fields
"nid" and "cid" or "nid" and "in_sob" and "out_sob". The field "in_cob" is
only set if the described CAN variable needs an input CAN object, the field
"out_cob" is only set if the CAN variable needs an output CAN object.
 
Here are some examples:
 
>>> def t(multi, access, server, nid, cid=None, in_sob= None, out_sob= None):
...     d={"multi":multi, "access":access, "server":server,
...        "nid": nid}
...     if cid is not None:
...         d["cid"]= cid
...     if in_sob is not None:
...         d["in_sob"]= in_sob
...     if out_sob is not None:
...         d["out_sob"]= out_sob
...     calc_cob(d)
...     print "in:",d.get("in_cob"),"  out:",d.get("out_cob")
>>> t(False,'r',False,5,9)
in: 1157   out: None
>>> t(False,'w',False,5,9)
in: None   out: 1221
>>> t(False,'rw',False,5,9)
in: 1157   out: 1221
>>> t(False,'r',True,5,9)
in: None   out: 1157
>>> t(False,'w',True,5,9)
in: 1221   out: None
>>> t(False,'rw',True,5,9)
in: 1221   out: 1157
>>> t(True,'r',False,5,9)
in: 1157   out: 1221
>>> t(True,'w',False,5,9)
in: None   out: 1221
>>> t(True,'rw',False,5,9)
in: 1157   out: 1221
>>> t(False,'rw',False,5,in_sob=11,out_sob=13)
in: 709   out: 837
>>> t(False,'r',False,5,in_sob=11)
in: 709   out: None
>>> t(False,'w',False,5,out_sob=13)
in: None   out: 837
cidnid2cob(cid, d, nid)
calculate cid and nid from cob.
 
parameters:
    cid    - the CAN channel id (cid)
    d      - the direction flag, must be 0 or 1
    nid    - the CAN node id (nid)
 
returns:
    the CAN object id (COB)
 
Here are some examples:
 
>>> _redirect_warnings() # catch warnings in this doctest
>>> cidnid2cob(-1,0,0)
cidnid2cob(): cid out of range: -1
>>> cidnid2cob(13,0,0)
cidnid2cob(): cid out of range: 13
>>> cidnid2cob(2,3,0)
cidnid2cob(): d out of range: 3
>>> cidnid2cob(2,0,0)
cidnid2cob(): nid out of range: 0
>>> cidnid2cob(2,0,64)
cidnid2cob(): nid out of range: 64
>>> cidnid2cob(2,0,33)
289
>>> hex(cidnid2cob(0x8,1,0x2d))
'0x46d'
>>> hex(cidnid2cob(0x8,0,0x2d))
'0x42d'
cob2cidnid(cob)
calculate a cob from cid and nid.
 
parameters:
    cob    - the CAN object id (COB)
 
returns:
    (cid,d,nid) - a tuple consisting of the channel id (cid), the direction
                  flag d and the node id (nid).
 
Here are the meanings of the bits within a cob:
 
bit 0-5: nid
6      : direction : 1 for read-objects on server
7-10   : cid
 
Here are some examples:
 
>>> cob2cidnid(-1)
cob2cidnid(): cob is invalid: -1
>>> cob2cidnid(2048)
cob2cidnid(): cob is invalid: 2048
>>> cob2cidnid(2047)
(15, 1, 63)
>>> cob2cidnid(0x46d)
(8, 1, 45)
>>> cob2cidnid(0x42d)
(8, 0, 45)
cob2sobnid(cob)
convert a cob to sob, nid.
 
parameters:
    cob    - the CAN object id (COB)
 
returns:
    (sob,nid) - a tuple consisting of the sob object id (sob) and the node
                id (nid)
 
Here are the meanings of the bits within a cob:
 
bit 0-5: nid
6-10   : sob
 
Here are some examples:
 
>>> cob2sobnid(-1)
cob2sobnid(): cob is invalid: -1
>>> cob2sobnid(2048)
cob2sobnid(): cob is invalid: 2048
>>> cob2sobnid(0x46d)
(17, 45)
complete(p)
complete the properties dict if some properties are missing.
 
parameters:
    p    - the property dictionary
 
returns:
    the property dictionary or <None> in case of an error.
 
This function *modifies* the property dictionary. It adds properties that
are missung but can be calculated from other properties or have sensible
defaults.
 
returns None in case of an error
 
>>> import pprint
>>> d={"access":"r", "type":"short", "in_cob":1157, "port":0}
>>> pprint.pprint(complete(d))
{'access': 'r',
 'array': False,
 'cid': 9,
 'in_cob': 1157,
 'in_sob': 18,
 'maxlength': 2,
 'multi': False,
 'multiplexor': 0,
 'nid': 5,
 'port': 0,
 'raw': False,
 'server': False,
 'signed': False,
 'type': 'short'}
>>> d={"access":"w", "type":"short", 
...    "array": True, "arraysize":2, "out_cob":1221, "port":0}
>>> pprint.pprint(complete(d))
{'access': 'w',
 'array': True,
 'arraysize': 2,
 'cid': 9,
 'maxlength': 4,
 'multi': False,
 'multiplexor': 0,
 'nid': 5,
 'out_cob': 1221,
 'out_sob': 19,
 'port': 0,
 'raw': False,
 'server': False,
 'signed': False,
 'type': 'short'}
>>> d={"access":"rw", "type":"short", "multi": True, "multiplexor": 10,
...    "server": True, "nid": 5, "cid": 9, "port": 1}
>>> pprint.pprint(complete(d))
{'access': 'rw',
 'array': False,
 'cid': 9,
 'in_cob': 1221,
 'maxlength': 3,
 'multi': True,
 'multiplexor': 10,
 'nid': 5,
 'out_cob': 1157,
 'port': 1,
 'raw': False,
 'server': True,
 'signed': False,
 'type': 'short'}
>>> d={"access":"r", "type":"short", "in_cob":1157, 
...    "raw": True, "signed": True, "port":0}
>>> pprint.pprint(complete(d))
{'access': 'r',
 'array': False,
 'cid': 9,
 'in_cob': 1157,
 'in_sob': 18,
 'maxlength': 2,
 'multi': False,
 'multiplexor': 0,
 'nid': 5,
 'port': 0,
 'raw': True,
 'server': False,
 'signed': True,
 'type': 'short'}
decode(str_)
create a property dictionary from a CAN link string.
 
parameters:
    str_    - the can link string
 
returns:
    a property dictionary or <None> in case of an error.
 
This function decodes the CAN link string and returns the property
dictionary. 
 
Here are some examples:
 
>>> import pprint
>>> pprint.pprint(decode('@a t 6 3 0 485 0 3e8 7d0 3'))
{'access': 'r',
 'array': True,
 'arraysize': 3,
 'cid': 9,
 'in_cob': 1157,
 'in_sob': 18,
 'inhibit': 100.0,
 'maxlength': 6,
 'multi': False,
 'multiplexor': 0,
 'nid': 5,
 'out_cob': 0,
 'port': 3,
 'raw': False,
 'server': False,
 'signed': True,
 'timeout': 2000,
 'type': 'short'}
>>> pprint.pprint(decode('@l L 5 3 26d 16d 7 3e8 7d0 0'))
{'access': 'rw',
 'array': False,
 'arraysize': 0,
 'in_cob': 365,
 'in_sob': 5,
 'inhibit': 100.0,
 'maxlength': 5,
 'multi': True,
 'multiplexor': 7,
 'nid': 45,
 'out_cob': 621,
 'out_sob': 9,
 'port': 3,
 'raw': False,
 'server': True,
 'signed': False,
 'timeout': 2000,
 'type': 'long'}
encode(p)
convert a property dict to a CAN link string.
 
parameters:
    p    - a property dictionary
 
returns:
    a CAN link string
 
Here are some examples:
 
>>> p=  {'access': 'r',
...      'array': True,
...      'arraysize': 3,
...      'cid': 9,
...      'in_cob': 1157,
...      'inhibit': 100.0,
...      'maxlength': 6,
...      'multi': False,
...      'multiplexor': False,
...      'nid': 5,
...      'port': 3,
...      'raw': False,
...      'server': False,
...      'signed': True,
...      'timeout': 2000,
...      'type': 'short'}
>>> encode(p)
'@a t 6 3 0 485 0 3e8 7d0 3'
>>> p=  {'access': 'rw',
...      'array': False,
...      'in_cob': 365,
...      'in_sob': 5,
...      'inhibit': 100.0,
...      'maxlength': 5,
...      'multi': True,
...      'multiplexor': 7,
...      'nid': 45,
...      'out_cob': 621,
...      'out_sob': 9,
...      'port': 3,
...      'raw': False,
...      'server': True,
...      'signed': False,
...      'timeout': 2000,
...      'type': 'long'}
>>> encode(p)
'@l L 5 3 26d 16d 7 3e8 7d0 0'
explain(fields=None)
returns a string with explanations.
 
This function returns a string that contains a short explanation on each
string that is provided in given list. When called with no parameter, is
returns an explanation on each CAN link field known in this module.
 
parameters:
    fields  - A list of field names, this parameter is optional
 
returns:
    a string with explanations.
 
Here are some examples:
 
>>> print explain(["cid","nid"])
cid:
  This is the connection-id of the CAN variable. Note that
  this parameter is optional
nid:
  This is the node-id of the server. Note that this parameter
  is optional
interview(tests=None)
create a CAN link by interviewing the user.
 
This function creates a CAN link definition by asking the user several
questions. Note that this function is interactive and uses simple terminal
I/O.
 
parameters:
    tests   - an optional list of strings, a simulated input. This is only
              used for the doctest.
 
returns:
    a property dictionary.
 
>>> import pprint
>>> p= interview(["1",   # client
...               "1",   # read-only
...               "1",   # basic
...               "3",   # short
...               "1",   # signed
...               "2",   # array
...               "3",   # arraysize 3
...               "1",   # not raw
...               "3",   # port
...               "3",   # give cid,nid
...               "5",   # nid
...               "9",   # cid
...               100,   # inhibit
...               2000]) # timeout
please select one:
 1) client
 2) server
1
please select one:
 1) read-only
 2) write-only
 3) read-write
1
please select one:
 1) basic variable
 2) multiplex variable
1
please select one:
 1) string
 2) char
 3) short
 4) mid
 5) long
 6) zero
3
please select one:
 1) signed
 2) unsigned
1
please select one:
 1) simple
 2) array
2
please enter the array-size:
3
please select one:
 1) not raw
 2) raw
1
please enter the port number:
3
please select one:
 1) specify in-cob,out-cob
 2) specify sob, nid
 3) specify cid, nid
3
please enter the server node-id:
5
please enter the channel-id:
9
please enter the inhibit-time in [ms]:
100
please enter the timeout-time in [ms]:
2000
>>> pprint.pprint(p)
{'access': 'r',
 'array': True,
 'arraysize': 3,
 'cid': 9,
 'in_cob': 1157,
 'inhibit': 100.0,
 'maxlength': 6,
 'multi': False,
 'multiplexor': 0,
 'nid': 5,
 'port': 3,
 'raw': False,
 'server': False,
 'signed': True,
 'timeout': 2000,
 'type': 'short'}
>>> p= interview(["2",   # server
...               "3",   # read-write
...               "2",   # multiplexed
...               "5",   # long
...               "2",   # unsigned
...               "1",   # no array
...               "1",   # not raw
...               "3",   # port
...               "1",   # give in-cob, out-cob
...               "12",  # in-cob
...               "34",  # out-cob
...               "7",   # multiplexor
...               100,   # inhibit
...               2000]) # timeout
please select one:
 1) client
 2) server
2
please select one:
 1) read-only
 2) write-only
 3) read-write
3
please select one:
 1) basic variable
 2) multiplex variable
2
please select one:
 1) string
 2) char
 3) short
 4) mid
 5) long
 6) zero
5
please select one:
 1) signed
 2) unsigned
2
please select one:
 1) simple
 2) array
1
please select one:
 1) not raw
 2) raw
1
please enter the port number:
3
please select one:
 1) specify in-cob,out-cob
 2) specify sob, nid
 3) specify cid, nid
1
please enter the cob of the incoming can object:
12
please enter the cob of the outgoing can object:
34
please enter the multiplexor:
7
please enter the inhibit-time in [ms]:
100
please enter the timeout-time in [ms]:
2000
>>> pprint.pprint(p)
{'access': 'rw',
 'array': False,
 'in_cob': 12,
 'inhibit': 100.0,
 'maxlength': 5,
 'multi': True,
 'multiplexor': 7,
 'out_cob': 34,
 'port': 3,
 'raw': False,
 'server': True,
 'signed': False,
 'timeout': 2000,
 'type': 'long'}
>>> p= interview(["2",   # server
...               "3",   # read-write
...               "2",   # multiplexed
...               "5",   # long
...               "2",   # unsigned
...               "1",   # no array
...               "1",   # not raw
...               "3",   # port
...               "1",   # give in-cob, out-cob
...               "365", # in-cob
...               "621", # out-cob
...               "7",   # multiplexor
...               100,   # inhibit
...               2000]) # timeout
please select one:
 1) client
 2) server
2
please select one:
 1) read-only
 2) write-only
 3) read-write
3
please select one:
 1) basic variable
 2) multiplex variable
2
please select one:
 1) string
 2) char
 3) short
 4) mid
 5) long
 6) zero
5
please select one:
 1) signed
 2) unsigned
2
please select one:
 1) simple
 2) array
1
please select one:
 1) not raw
 2) raw
1
please enter the port number:
3
please select one:
 1) specify in-cob,out-cob
 2) specify sob, nid
 3) specify cid, nid
1
please enter the cob of the incoming can object:
365
please enter the cob of the outgoing can object:
621
please enter the multiplexor:
7
please enter the inhibit-time in [ms]:
100
please enter the timeout-time in [ms]:
2000
>>> pprint.pprint(p)
{'access': 'rw',
 'array': False,
 'in_cob': 365,
 'in_sob': 5,
 'inhibit': 100.0,
 'maxlength': 5,
 'multi': True,
 'multiplexor': 7,
 'nid': 45,
 'out_cob': 621,
 'out_sob': 9,
 'port': 3,
 'raw': False,
 'server': True,
 'signed': False,
 'timeout': 2000,
 'type': 'long'}
maxlength(p)
return the CAN data length of the type in the property dict.
 
parameters:
    p    - the property dictionary
 
returns:
    CAN object length, an integer.
 
Here are some examples:
 
>>> maxlength({"type":"char","array":False,"multi":False})
1
>>> maxlength({"type":"short","array":False,"multi":False})
2
>>> maxlength({"type":"mid","array":False,"multi":False})
3
>>> maxlength({"type":"long","array":False,"multi":False})
4
>>> maxlength({"type":"zero","array":False,"multi":False})
0
>>> maxlength({"type":"short","array":True,"arraysize":3,"multi":False})
6
>>> maxlength({"type":"short","array":False,"multi":True})
3
>>> maxlength({"type":"short","array":True,"arraysize":3,"multi":True})
7
pretty_print(p)
pretty-print a property dictionary.
 
parameters:
    p    - the property dictionary
 
returns:
    a text describing the property dictionary, a single string
 
Here are some examples:
 
>>> p=  {'access': 'r',
...      'array': True,
...      'arraysize': 3,
...      'cid': 9,
...      'in_cob': 1157,
...      'inhibit': 100.0,
...      'maxlength': 6,
...      'multi': False,
...      'multiplexor': 0,
...      'nid': 5,
...      'port': 3,
...      'raw': False,
...      'server': False,
...      'signed': True,
...      'timeout': 2000,
...      'type': 'short'}
>>> print pretty_print(p)
variable-type: client basic read-only
data-type    : array of signed short
length       :    6 bytes
port         :    3
in-cob       : 1157
node-id      :    5
channel-id   :    9
inhibit      :  100.0 [ms]
timeout      : 2000   [ms]
arraysize    :    3 elements
>>> p=  {'access': 'rw',
...      'array': False,
...      'in_cob': 365,
...      'in_sob': 5,
...      'inhibit': 100.0,
...      'maxlength': 5,
...      'multi': True,
...      'multiplexor': 7,
...      'nid': 45,
...      'out_cob': 621,
...      'out_sob': 9,
...      'port': 3,
...      'raw': False,
...      'server': True,
...      'signed': False,
...      'timeout': 2000,
...      'type': 'long'}
>>> print pretty_print(p)
variable-type: server multiplex read-write
data-type    : unsigned long
length       :    5 bytes
port         :    3
out-cob      :  621
in-cob       :  365
node-id      :   45
in-sob       :    5
out-sob      :    9
multiplexor  :    7
inhibit      :  100.0 [ms]
timeout      : 2000   [ms]
sobnid2cob(sob, nid)
calculate cob from sob and nid.
 
parameters:
    sob   - the sub object id (sob)
    nid   - the CAN node id (nid)
 
returns:
    cob   - the can object ID
 
Here are some examples:
 
>>> sobnid2cob(27,1)
sobnid2cob(): sob out of range: 27
>>> sobnid2cob(-1,1)
sobnid2cob(): sob out of range: -1
>>> sobnid2cob(0,0)
sobnid2cob(): nid out of range: 0
>>> sobnid2cob(0,64)
sobnid2cob(): nid out of range: 64
>>> sobnid2cob(0,63)
63
>>> sobnid2cob(11,23)
727
>>> hex(sobnid2cob(0x12,0x34))
'0x4b4'
tab_print(p=None)
return a can link print can link in table format.
 
This function can be used to print a property dictionaries in a table. If
the parameter p is not given, the function returns the table heading.
 
parameters:
    p    - the property dictionary, this parameter is optional
 
returns:
    a line of the table
 
Here are some examples:
 
>>> p0= {'access': 'r',
...      'array': True,
...      'arraysize': 3,
...      'cid': 9,
...      'in_cob': 1157,
...      'inhibit': 100.0,
...      'maxlength': 6,
...      'multi': False,
...      'multiplexor': False,
...      'nid': 5,
...      'port': 3,
...      'raw': False,
...      'server': False,
...      'signed': True,
...      'timeout': 2000,
...      'type': 'short'}
>>> p1= {'access': 'rw',
...      'array': False,
...      'in_cob': 365,
...      'in_sob': 5,
...      'inhibit': 100.0,
...      'maxlength': 5,
...      'multi': True,
...      'multiplexor': 7,
...      'nid': 45,
...      'out_cob': 621,
...      'out_sob': 9,
...      'port': 3,
...      'raw': False,
...      'server': True,
...      'signed': False,
...      'timeout': 2000,
...      'type': 'long'}
>>> for e in [None,p0,p1]:
...     print tab_print(e)
srv/cln mul rw arr  s type   len prt   in  out mplx    inh  tmo asz
client  bas  r arr  s short    6   3 1157   -1   -1  100.0 2000   3
server  mlt rw sing u long     5   3  365  621    7  100.0 2000   0

 
Data
        VERSION = '1.0'