Skip to content

Commit

Permalink
Merge c7ffb78 into 626d2fb
Browse files Browse the repository at this point in the history
  • Loading branch information
peternewman committed Dec 22, 2014
2 parents 626d2fb + c7ffb78 commit d566f2e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 55 deletions.
4 changes: 2 additions & 2 deletions examples/ola-rdm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void ParseOptions(int argc, char *argv[], options *opts) {
* Display the help for get_pid
*/
void DisplayGetPidHelp(const options &opts) {
cout << "usage: " << opts.cmd <<
cout << "Usage: " << opts.cmd <<
" --universe <universe> --uid <uid> <pid> <value>\n"
"\n"
"Get the value of a pid for a device.\n"
Expand All @@ -156,7 +156,7 @@ void DisplayGetPidHelp(const options &opts) {
* Display the help for set_pid
*/
void DisplaySetPidHelp(const options &opts) {
cout << "usage: " << opts.cmd <<
cout << "Usage: " << opts.cmd <<
" --universe <universe> --uid <uid> <pid> <value>\n"
"\n"
"Set the value of a pid for a device.\n"
Expand Down
103 changes: 74 additions & 29 deletions python/ola/PidStore.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,24 @@ def RequestSupported(self, command_class):
"""Check if this PID allows a command class."""
return self._requests.get(command_class) is not None

def GetRequest(self, command_class):
return self._requests.get(command_class)

def GetRequestField(self, command_class, field_name):
return filter(lambda field: field.name == field_name,
self._requests.get(command_class).GetAtoms())[0]

def ResponseSupported(self, command_class):
"""Check if this PID responds to a command class."""
return self._requests.get(command_class) is not None

def GetResponse(self, command_class):
return self._responses.get(command_class)

def GetResponseField(self, command_class, field_name):
return filter(lambda field: field.name == field_name,
self._responses.get(command_class).GetAtoms())[0]

def ValidateAddressing(self, args, command_class):
"""Run the validators."""
validators = self._validators.get(command_class)
Expand Down Expand Up @@ -314,33 +332,8 @@ def Pack(self, args):
value = self._labels.get(arg)

# not a labeled value
if value is None and self._multiplier >= 0:
try:
value = int(args[0])
except ValueError, e:
raise ArgsValidationError(e)

multiplier = 10 ** self._multiplier
if value % multiplier:
raise ArgsValidationError('Conversion will lose data: %d -> %d' %
(value, (value / multiplier * multiplier)))
value = value / multiplier

elif value is None:
try:
value = float(args[0])
except ValueError, e:
raise ArgsValidationError(e)

scaled_value = value * 10 ** abs(self._multiplier)

fraction, int_value = math.modf(scaled_value)

if fraction:
raise ArgsValidationError(
'Conversion will lose data: %s -> %s' %
(value, int_value * (10.0 ** self._multiplier)))
value = int(int_value)
if value is None:
value = self._AccountForMultiplierPack(args[0])

for range in self._ranges:
if range.Matches(value):
Expand All @@ -352,7 +345,7 @@ def Pack(self, args):
return super(IntAtom, self).Pack([value])

def Unpack(self, data):
return self._AccountForMultiplier(super(IntAtom, self).Unpack(data))
return self._AccountForMultiplierUnpack(super(IntAtom, self).Unpack(data))

def GetDescription(self, indent=0):
indent = ' ' * indent
Expand All @@ -363,6 +356,22 @@ def GetDescription(self, indent=0):
return ('%s%s: <%s> %s' % (indent, self.name, self._GetAllowedRanges(),
increment))

def DisplayValue(self, value):
"""Converts a raw value, e.g. UInt16 (as opposed to an array of bytes) into
the value it would be displayed as, e.g. float to 1 D.P.
This takes into account any multipliers set for the field.
"""
return self._AccountForMultiplierUnpack(value)

def RawValue(self, value):
"""Converts a display value, e.g. float to 1 D.P. into a raw value UInt16
(as opposed to an array of bytes) it would be transmitted as.
This takes into account any multipliers set for the field.
"""
return self._AccountForMultiplierPack(value)

def _GetAllowedRanges(self):
values = self._labels.keys()

Expand All @@ -377,12 +386,42 @@ def _GetAllowedRanges(self):
return ('%s' % ', '.join(values))


def _AccountForMultiplier(self, value):
def _AccountForMultiplierUnpack(self, value):
new_value = value * (10 ** self._multiplier)
if self._multiplier < 0:
new_value = round(new_value, abs(self._multiplier))
return new_value

def _AccountForMultiplierPack(self, value):
if self._multiplier >= 0:
try:
new_value = int(value)
except ValueError, e:
raise ArgsValidationError(e)

multiplier = 10 ** self._multiplier
if new_value % multiplier:
raise ArgsValidationError(
'Conversion will lose data: %d -> %d' %
(new_value, (new_value / multiplier * multiplier)))
new_value = new_value / multiplier

else:
try:
new_value = float(value)
except ValueError, e:
raise ArgsValidationError(e)

scaled_value = new_value * 10 ** abs(self._multiplier)

fraction, int_value = math.modf(scaled_value)

if fraction:
raise ArgsValidationError(
'Conversion will lose data: %s -> %s' %
(new_value, int_value * (10.0 ** self._multiplier)))
new_value = int(int_value)
return new_value

class Int8(IntAtom):
"""A single signed byte field."""
Expand Down Expand Up @@ -602,6 +641,12 @@ def __init__(self, name, atoms, **kwargs):
# None for variable sized groups
self._group_size = self._VerifyStructure()

def HasAtoms(self):
return (len(self._atoms) > 0)

def GetAtoms(self):
return self._atoms

@property
def min(self):
return self._min
Expand Down
66 changes: 44 additions & 22 deletions tools/rdm/TestDefinitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,8 @@ def VerifyResult(self, response, fields):
continue

supported_parameters.append(param_id)
if param_id >= RDM_MANUFACTURER_PID_MIN and param_id <= RDM_MANUFACTURER_PID_MAX:
if (param_id >= RDM_MANUFACTURER_PID_MIN and
param_id <= RDM_MANUFACTURER_PID_MAX):
manufacturer_parameters.append(param_id)

pid_store = PidStore.GetStore()
Expand Down Expand Up @@ -4384,14 +4385,16 @@ def Test(self):
return

delay_time = self.max_delay_time
delay_time_field = self.pid.GetRequestField(RDM_SET, 'loss_of_signal_delay')
# 0xffff means 'fail mode not supported'
if self.max_delay_time * 10 < 0xfffe:
delay_time = (self.max_delay_time * 10 + 1) / 10.0 # increment by 1
if delay_time_field.RawValue(self.max_delay_time) < (0xffff - 1):
delay_time = delay_time_field.DisplayValue(delay_time_field.RawValue(self.max_delay_time) + 1) # increment by 1

hold_time = self.max_hold_time
hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time')
# 0xffff means 'fail mode not supported'
if self.max_hold_time * 10 < 0xfffe:
hold_time = (self.max_hold_time * 10 + 1) / 10.0 # increment by 1
if hold_time_field.RawValue(self.max_hold_time) < (0xffff - 1):
hold_time = hold_time_field.DisplayValue(hold_time_field.RawValue(self.max_hold_time) + 1) # increment by 1

if self.Property('set_dmx_fail_mode_supported'):
self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode))
Expand Down Expand Up @@ -4425,14 +4428,16 @@ def Test(self):
return

delay_time = self.min_delay_time
delay_time_field = self.pid.GetRequestField(RDM_SET, 'loss_of_signal_delay')
# 0xffff means 'fail mode not supported'
if self.min_delay_time * 10 > 1 and self.min_delay_time * 10 < 0xffff:
delay_time = (self.min_delay_time * 10 - 1) / 10.0 # decrement by 1
if delay_time_field.RawValue(self.min_delay_time) > 1 and delay_time_field.RawValue(self.min_delay_time) < 0xffff:
delay_time = delay_time_field.DisplayValue(delay_time_field.RawValue(self.min_delay_time) - 1) # decrement by 1

hold_time = self.min_hold_time
hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time')
# 0xffff means 'fail mode not supported'
if self.min_hold_time * 10 > 1 and self.min_hold_time * 10 < 0xffff:
hold_time = (self.min_hold_time * 10 - 1) / 10.0 # decrement by 1
if hold_time_field.RawValue(self.min_hold_time) > 1 and hold_time_field.RawValue(self.min_hold_time) < 0xffff:
hold_time = hold_time_field.DisplayValue(hold_time_field.RawValue(self.min_hold_time) - 1) # decrement by 1

if self.Property('set_dmx_fail_mode_supported'):
self.AddIfSetSupported(self.AckSetResult(action=self.GetFailMode))
Expand Down Expand Up @@ -4638,14 +4643,18 @@ def Test(self):
return

delay_time = self.max_delay_time
delay_time_field = self.pid.GetRequestField(RDM_SET, 'startup_delay')
# 0xffff means 'startup mode not supported'
if self.max_delay_time * 10 < 0xfffe:
delay_time = (self.max_delay_time * 10 + 1) / 10.0 # increment by 1
if delay_time_field.RawValue(self.max_delay_time) < (0xffff - 1):
delay_time = delay_time_field.DisplayValue(
delay_time_field.RawValue(self.max_delay_time) + 1) # increment by 1

hold_time = self.max_hold_time
hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time')
# 0xffff means 'startup mode not supported'
if self.max_hold_time * 10 < 0xfffe:
hold_time = (self.max_hold_time * 10 + 1) / 10.0 # increment by 1
if hold_time_field.RawValue(self.max_hold_time) < (0xffff - 1):
hold_time = hold_time_field.DisplayValue(
hold_time_field.RawValue(self.max_hold_time) + 1) # increment by 1

if self.Property('set_dmx_startup_mode_supported'):
self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode))
Expand Down Expand Up @@ -4679,14 +4688,20 @@ def Test(self):
return

delay_time = self.min_delay_time
delay_time_field = self.pid.GetRequestField(RDM_SET, 'startup_delay')
# 0xffff means 'startup mode not supported'
if self.min_delay_time * 10 > 1 and self.min_delay_time * 10 < 0xffff:
delay_time = (self.min_delay_time * 10 - 1) / 10.0 # decrement by 1
if (delay_time_field.RawValue(self.min_delay_time) > 1 and
delay_time_field.RawValue(self.min_delay_time) < 0xffff):
delay_time = delay_time_field.DisplayValue(
delay_time_field.RawValue(self.min_delay_time) - 1) # decrement by 1

hold_time = self.min_hold_time
hold_time_field = self.pid.GetRequestField(RDM_SET, 'hold_time')
# 0xffff means 'startup mode not supported'
if self.min_hold_time * 10 > 1 and self.min_delay_time * 10 < 0xffff:
hold_time = (self.min_hold_time * 10 - 1) / 10.0 # decrement by 1
if (hold_time_field.RawValue(self.min_hold_time) > 1 and
hold_time_field.RawValue(self.min_hold_time) < 0xffff):
hold_time = hold_time_field.DisplayValue(
hold_time_field.RawValue(self.min_hold_time) - 1) # decrement by 1

if self.Property('set_dmx_startup_mode_supported'):
self.AddIfSetSupported(self.AckSetResult(action=self.GetStartupMode))
Expand Down Expand Up @@ -5939,7 +5954,8 @@ def CrossCheckPidSupportIsZero(self, pid_name, fields, key):

def CrossCheckPidSupportIsMax(self, pid_name, fields, key):
for key in ['min_%s' % key, 'max_%s' % key]:
if not (self.IsSupported(pid_name) or fields[key] == 0xffff):
if not (self.IsSupported(pid_name) or
fields[key] == self.pid.GetResponseField(RDM_GET, key).DisplayValue(0xffff)):
self.AddWarning(
'%s not supported, but %s in PRESET_INFO is not 0xffff' %
(pid_name, key))
Expand Down Expand Up @@ -6030,9 +6046,13 @@ def Test(self):
self.max_scene = self.Property('max_scene_number')
preset_info = self.Property('preset_info')
self.min_fade = preset_info.get('min_preset_fade_time', 0)
self.max_fade = preset_info.get('max_preset_fade_time', 0xffff)
self.max_fade = preset_info.get(
'max_preset_fade_time',
self.pid.GetResponseField(RDM_GET, 'up_fade_time').RawValue(0xffff))
self.min_wait = preset_info.get('min_preset_wait_time', 0)
self.max_wait = preset_info.get('max_preset_wait_time', 0xffff)
self.max_wait = preset_info.get(
'max_preset_wait_time',
self.pid.GetResponseField(RDM_GET, 'wait_time').RawValue(0xffff))

if self.max_scene is None or self.max_scene == 0:
self.SetNotRun('No scenes supported')
Expand Down Expand Up @@ -6200,8 +6220,10 @@ def Test(self):
self.SetNotRun('No writeable scenes found')
return

self.max_fade = 0xffff
self.max_wait = 0xffff
self.max_fade = round(self.pid.GetRequestField(
RDM_SET, 'up_fade_time').RawValue(0xffff), 1)
self.max_wait = round(self.pid.GetRequestField(
RDM_SET, 'wait_time').RawValue(0xffff), 1)
preset_info = self.Property('preset_info')
if preset_info is not None:
self.max_fade = round(preset_info['max_preset_fade_time'], 1)
Expand Down
4 changes: 2 additions & 2 deletions tools/rdm/TestMixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ class SetDmxFailModeMixin(object):
REQUIRES = ['dmx_fail_settings', 'preset_info', 'set_dmx_fail_mode_supported']
CATEGORY = TestCategory.DMX_SETUP

INFINITE_TIME = 6553.5
INFINITE_TIME = 6553.5 # 0xffff * 10^-1 (multiplier)

def ResetState(self):
if not self.PidSupported():
Expand Down Expand Up @@ -693,7 +693,7 @@ class SetDmxStartupModeMixin(object):
'set_dmx_startup_mode_supported']
CATEGORY = TestCategory.DMX_SETUP

INFINITE_TIME = 6553.5
INFINITE_TIME = 6553.5 # 0xffff * 10^-1 (multiplier)

def ResetState(self):
if not self.PidSupported():
Expand Down

0 comments on commit d566f2e

Please sign in to comment.