Skip to content
ggodart edited this page Jan 5, 2021 · 8 revisions

Musica

See original

SYNOPSIS

Important Note:

Because the new FM-Tuner keypads (and possibly other newer keypads?) take forever (minutes) to respond to the StatVer command, their version is stored in the persistant Misterhouse %Save hash. This means that if you change the physical keypad, you'll need to stop MisterHouse, edit data_dir/mh_temp.saved_states.persistent, and search for 'Musica' and remove or modify the entry for the zone you changed. Then start MisterHouse back up. If you simply remove a keypad, just take the entry for that zone out of your .mht file -- you don't need to worry about %Save.

Also, some keypads never respond to the StatVer command MisterHouse sends to try to find the version of each keypad. Watch your print log and if You see StatVer being re-sent over and over again for a specific keypad, you may want to specify its version in your .mht file as so:

      MUSICA_ZONE, music_kitchen,    Musica, 1, 40822

My keypads (version 40822) do respond to StatVer after 2-3 minutes and then this version is stored by the Musica module in the persistent %Save hash.

The only keypad versions I know are:

      30419: MU4601 keypad
      40822: MU4602 FM-Tuner keypad

DESCRIPTION

Allows control of the Musica whole-house audio system by Netstreams over the RS232 port. This system has excellent controllability through Misterhouse and provides 6 zones and 4 sources with very nice keypads. http://www.netstreams.com Broken link

If you are interested in installing a Netstreams Musica system yourself, contact me and I can put you in contact with somebody who can give you a good price.

Note that you must use a null-modem cable between the Musica system and your Misterhouse computer.

This module uses Rev 2.0 of the Musica RS-232 protocol.

INHERITS

Serial_Item

INI PARAMETERS

You can define any number of Musica systems, but each one requires its own serial port. To begin with, come up with a name for your object such as $Musica. Then add an entry to your mh.ini file:

Musica_serial_port=/dev/ttyS9

If you wanted to define two Musica systems, you would just choose two unique names:

Musica1_serial_port=/dev/ttyS9
Musica2_serial_port=/dev/ttyS10

Items.mht

Once you have specified which serial port to use, simply define the main object and your zone objects in your .mht file:

#
MUSICA, Musica
MUSICA_ZONE, music_kitchen,    Musica, 1
MUSICA_ZONE, music_master_bed, Musica, 2

This would define the object $Musica, with zone 1 named $music_kitchen, and zone 2 named $music_master_bed. If you have more than one system to control, just use the same names as you used in your .ini file:

MUSICA, Musica1
MUSICA, Musica2
MUSICA_ZONE, music_kitchen,     Musica1, 1
MUSICA_ZONE, music_master_bed,  Musica1, 2
MUSICA_ZONE, music_patio,       Musica2, 1
MUSICA_ZONE, music_dining_room, Musica2, 2

Finally, you can define an object representing each of the four Musica sources if you so desire. This is only necessary if you need to do something like start or stop an MP3 player or turn something on via X10 when a source is accessed, if you want to watch for users changing the source labels from keypads, or if you want to change the source labels from MisterHouse. Finally, if you want to watch for button presses or cause buttons to be pressed through MisterHouse, these are useful. These are not required for casual use.

MUSICA_SOURCE, mrhouse_speech, Musica, 1
MUSICA_SOURCE, am_fm_tuner,    Musica, 2
MUSICA_SOURCE, music_source3,  Musica, 3
MUSICA_SOURCE, music_source4,  Musica, 4

Interface Overview:

All objects (the main Musica object, the zone objects, and the source objects) will return various states (as documented below) when somebody performs any kind of action from a keypad.

If somebody changes the volume in a specific zone, for example, the object for that zone will have a state of 'volume_changed'. You can watch for those states as follows:

      if ($state = state_now $music_kitchen) {
         print_log "Kitchen keypad new state: $state";
      }

Note that when changes are made FROM MisterHouse (using the various controlling functions such as set_volume()) any resulting object state changes will have the set_by set to 'misterhouse'. By contrast, new states initiated by the keypad or Musica remote control have a set_by of 'keypad'. You can also see that your command took effect by calling get_volume() and seeing that it returns the volume you set. Note that this function will return your new value only after your command has been sent to the Musica system and it has confirmed your command. If there is a large queue of pending commands this can take several seconds.

Also, many functions can be called on either the main Musica object or one only one zone object. You can, for example, call $Musica->set_volume('100%') to set all zones to 100% volume or call $music_kitchen->set_volume('100%') to only change the volume of one zone. But even if you change the volume of all zones using the main object, you must still call get_volume() on the zone objects since the system as a whole doesn't actually have a volume.

Finally, if any object returns a state of 'error', it means that an error was encountered with the initialization of the system (i.e. a zone keypad was not found) or there was a problem executing one of your commands. The error will be displayed in the print log but you can also call get_last_error() on any object to see this error message.

Controlling either all zones or one zone:

These functions can all be called on the main Musica object to influence all zones or can be called on one specific zone object:

Method Description
set_treble(level) Sets the treble level for the zone. Valid values are -14 through 14 with 0 being the default (note that the keypads only have a resolution of two, such as -4, -2, 0, 2, 4, and a value such as 1 will be the same as 0 or 2).
set_bass(level) Sets the bass level for the zone. Valid values are -14 through 14 with 0 being the default (note that the keypads only have a resolution of two, such as -4, -2, 0, 2, 4, and a value such as 1 will be the same as 0 or 2).
set_source(identifier) Changes zone or zones to specified source. The parameter can be a number 1-4, the letter 'E' for the local expansion port, and the letter 'F' for the integrated FM tuner. the label assigned to a specific source (such as 'MP3'), or a source object. Examples:
$zone1_obj->set_source(1);
$Musica->set_source('E');
$zone1_obj->set_source('MP3');
$Musica->set_source($source1_obj);
set_volume(level) Sets the volume of one or all zones, where the level specified must range from 0 to 35. Can also be specified as a percentage where '0%' is off and '100%' is full volume.
set_balance(level) Sets the balance where -7 is full-left, +7 is full-right, and 0 is centered.
mute() Mutes one or all zones.
unmute() Unmutes one or all zones.
loudness_on() Turns on loudness in one or all zones.
loudness_off() Turns off loudness in one or all zones.
internal_amp() Use only the internal amplifier.
both_amps() Use both internal and external amplifiers.
external_amp() Use only the external amplifier.
green_backlight() Set backlight to the color green.
amber_backlight() Set backlight to the color amber.
white_backlight() Set backlight to the color white (instead of green when applicable).
blue_backlight() Set backlight to the color blue (instead of amber when applicable).
set_backlight_brightness(level) Sets backlight level to a value between 0 and 8 where 0 is off and 8 is full brightness. Can also be specified with a percentage where '0%' is off and '100%' is full brightness.
nudge_volume_down() Reduces the volume one notch.
nudge_volume_up() Increases the volume one notch.
nudge_bass_down() Reduces the bass one notch.
nudge_bass_up() Increases the bass one notch.
nudge_treble_down() Reduces the treble one notch.
nudge_treble_up() Increases the treble one notch.
nudge_balance_left() Balance shifted one notch to the left.
nudge_balance_right() Balance shifted one notch to the right.
lock_menu() Locks the menu on the keypad to prevent the user from entering the setup menu. Source selection and volume can still be changed.
unlock_menu() Unlocks the menu.
set_preset_label(number, label) Sets FM preset 1-8 to specified numeric or text label. Label must be one listed in %source_name_to_number_30419.
set_preset_frequency(number, freq) Sets FM preset 1-8 to specified frequency, where 8950 is 89.5, for example.

Controlling the Musica system object:

The following functions allow you to make changes to the Musica system as a whole from MisterHouse.

Method Description
all_off() Turn off all zones.

Retrieving data from the Musica system object:

Method Description
get_object_version() Returns the version of the Musica object.
get_port_name() Returns the name of the serial port used for this object.
get_zones() Returns list of zone objects associated with this system.
get_sources() Returns list of source objects associated with this system.
get_adc_version() Returns the version string as reported by the Audio Distribution Center.

Monitoring the Musica system object:

Following is a list of states that may be returned by the Musica system:

   error: An error has occurred, call get_last_error() for details.

Controlling the Musica zone objects using functions:

The following functions allow you to make changes to a specific Musica zone from MisterHouse.

Method Description
set_source(source) Sets the zone to the specified source, where 'source' is a number between 1 and 4 or E for the local expansion source. Turns the zone ON if it is not already on.
turn_off() Turns off the zone.
nudge_source_up() Switches to the next source (must already be on).
nudge_source_down() Switches to the previous source (must already be on).
delay_off(seconds) Automatically turn the zone off in the specified number of seconds. Timer is cancelled if the user selects a new source or if this function is called with '0' for the argument. Also can be reset by calling this function again. Returns current delay if no argument is provided.

Controlling the Musica zone objects using set()

The following input states are recognized by the Musica zone objects:

    off: Turn zone off
     1: Turn to source 1
     2: Turn to source 2
     3: Turn to source 3
     4: Turn to source 4
     E: Turn to external input
     volumeXX: Set volume where XX ranges from 0 to 35
     mute: Mutes the zone
     unmute: Unmutes the zone

Retrieving data from the Musica zone object:

Method Description
get_musica_obj() Returns the main musica object.
get_zone_num() Returns the zone number (from 1 to 6) for this object.
get_keypad_version() Returns the version number returned by the keypad.
get_last_on_time() Returns the last time the keypad was turned on (in Epoch format, as $::Time expresses it)
get_source() Returns the currently-selected source number, or 0 if off.
get_source_obj() Returns the currently-selected source object.
get_volume() Returns the volume, from 0 to 35.
get_bass_level() Returns the bass level from -14 to 14.
get_treble_level() Returns the bass level from -14 to 14.
get_balance() Returns the balance where -7 is full-left, 7 is full-right, and 0 is centered.
get_loudness() Returns 1 if on, 0 if off.
get_mute() Returns 1 if on, 0 if off.
get_blcolor() Returns 'green' or 'amber' to indicate backlight color. ('green' == 'white' and 'amber' == 'blue' on applicable keypads)
get_brightness() Returns backlight brightness from 0 to 8 where 0 means that the backlight is currently off.
get_audioport() Returns 1 if the audioport is connected.
get_amp() Returns 'room_amp', 'both', or 'external_amp'.
get_locked() Returns 1 if the keypad is locked.
get_overheat() Returns 1 if the keypad is overheated.
get_button_labels() Returns a list of the names of the 12 programmable buttons on the Musica keypad and remote.
press_button(button) Sends the IR code associated with pressing the specified button for this source. Button can be specified as either a number from 1 to 12 or as a label as returned by get_button_labels().
hold_button(button) Sends the IR code associated with holding the specified button for this source. Button can be specified as either a number from 1 to 12 or as a label as returned by get_button_labels().

Monitoring the Musica zone objects:

You can watch for state changes of the Musica zone object to see when a user changes the system in a way that affects a particular zone.

   error: An error has occurred, call get_last_error() for details.
   zone_on: The zone was turned on from an off state.
   zone_off: The zone was turned off from an on state.
   source_changed: The zone is already on and a user changed the source.
   changed_label_source_X: This zone keypad was used to change the label
      of source X (where X is a number from 1 to 4).
   volume_changed: Volume of the zone was changed.
   bass_changed: Bass level of the zone was changed.
   treble_changed: Treble level of the zone was changed.
   balance_changed: Balance level of the zone was changed.
   loudness_on: Loudness was enabled in the zone
   loudness_off: Loudness was disabled in the zone
   mute_on: This zone was muted.
   mute_off: This zone was unmuted.
   color_amber: The backlight color in this zone was changed to amber
      (or blue on applicable keypads).
   color_green: The backlight color in this zone was changed to green
      (or white on applicable keypads).
   backlight_on: The backlight was turned on (not given when the backlight
      comes on when the zone is turned on).
   backlight_off: The backlight was turned off.
   brightness_changed: The backlight brightness was changed.
   internal_amp: The user has chosen to use the internal amp only.
   internal_external_amp: The user has chosen to use the internal amp as well
      as an amp connected through the Expansion Interface Module.
   external_amp: Only the external amp is being used.
   locked: The keypad has been locked
   unlocked: The keypad has been unlocked
   overheated: The zone keypad has become overheated
   heat_normal: The zone keypad is no longer overheated
   button_pressed_*: A button was pressed (button names can be found after 
      this comment section or by calling get_button_labels() on a zone
      object).
   button_held_*: A button was pressed and held (button names can be found
      after this comment section or by calling get_button_labels() on a
      zone object).

Controlling the Musica source object

The following functions allow you to make changes to a particular source accessible from the Musica system.

Method Description
set_label(label) Sets the global label for this particular source. The label can either be given as a number between 1 and 30 or as a string. Only certain strings are allowed, and these strings can be determined by calling get_source_labels() on a source object.

Retrieving data from a Musica source object

Method Description
get_musica_obj() Returns the main musica object.
get_source_num() Returns the numerical source number associated with this source object.
get_label() Returns the label for the source as a string.
get_source_labels() Returns a list of valid source labels.
get_zones() Returns array of zones currently listening to this source.
get_usage_count() Returns the number of zones currently listening to this source.

Monitoring the Musica source objects

You can watch for state changes of the Musica source object to see when a user changes the system in a way that affects a particular source.

   error: An error has occurred, call get_last_error() for details.
   label_changed: somebody changed the label for this source from a keypad
      (call get_set_by() to find the object name of the keypad used to make
      the change).
   first_listener: the source now has a listener and it did not before.
   no_listeners: the only listener stopped listening and now nobody is using
      this particular source.
   listener_zone_X: zone X just selected this source.
   button_pressed_*: A button was pressed (button names can be found after
      this comment section or by calling get_button_labels()).
   button_held_*: A button was pressed and held (button names can be found
      after this comment section or by calling get_button_labels()).

Usage Examples:

To better understand the following examples, you should know that I have an array of MP3 players defined as:

      my @players;
      if ($Startup) {
         push @players, undef;
         foreach ('channel12', 'channel34', 'channel56', 'channel78') {
            push @players, new AlsaPlayer($_);
         }
      }

Then I create an array of all of the Musica::Source objects (which are already defined in my .mht file):

      my @musica_sources = ( $music_source1, $music_source2, $music_source3,
                             $music_source4 );

The 'first_listener' and 'no_listeners' states are handy to start/stop or pause/unpause something like an MP3 player, or even to power on/off sources or send out IR commands.

      foreach (@musica_sources) {
         if (state_now $_ eq 'first_listener') {
            $players[$_->get_source_num()]->unpause();
         }
         if (state_now $_ eq 'no_listeners') {
            $players[$_->get_source_num()]->pause();
         }
      }

To watch for button presses on all keypads and all sources and take the appropriate action:

      foreach (@musica_sources) {
         if (state_now $_ eq 'button_pressed_next') {
            $players[$_->get_source_num()]->next_song();
         }
         if (state_now $_ eq 'button_pressed_previous') {
            $players[$_->get_source_num()]->previous_song();
         }
         if (state_now $_ eq 'button_pressed_pause') {
            $players[$_->get_source_num()]->pause_toggle();
         }
         if (state_now $_ eq 'button_pressed_play') {
            $players[$_->get_source_num()]->unpause();
         }
      }

MUSICA SYSTEM BUGS:

[ADC Version M30419/Keypad Version R40822 (FM-Tuner)]

  • Keypad takes FOREVER (1-4 minutes) to respond to StatVer.
  • When you hold down a button on the keypad often times a button pressed event is sent right after the button held event. This code will ignore a press right after a hold.
  • Never sends back a copy of the ChangeAmp command nor does it send an EventData message back.
  • Does not respond to various commands like ChangeVol, ChangeBass, etc. Instead, sends an EventData message showing the changes (bug or protocol change?)

[ADC Version M30419/Keypad Version R30419]

  • If I send the ChangeSrc command at least three seconds after the ChangeStore command then it works fine. But if the gap is two seconds or less the zone never turns on like it should.

[ADC Version M30419/Keypad Version R30419]

  • ADC never responds to a NudgeSrc to a zone that is off. Workaround: only sends command if the zone is already on.

[ADC Version M30419/Keypad Version R30419]

  • ChangeSwOu command is always responded to with ChangeSwOu/1 whether you are trying to turn it on or off, and it seems to have no effect?

[ADC Version M30419/Keypad Version R30419]

  • The backlight brightness sent in EventData comes in as 0 until you change the backlight from its original value (or at least that is what happened to me).

##TODO:

  • Detect door/phone muting by watching for volume changes?
  • Implement IR_Dn/IR_Up?
  • ExeMenu* is not implemented as the ADC does not respond which makes it not like every other command plus I don't know why you would use it as it just allows you to navigate the menu system on a keypad but you can change everything directly through other messages anyways. But, for the record:
     ExeMenu/Zone/Command where Command is:
           1: Menu button
           2: Up Arrow
           3: Down Arrow
           4: Left Arrow
           5: Right Arrow

AUTHOR

Kirk Bauer [email protected]

SEE ALSO

None

Clone this wiki locally