Sign in   |  Join   |  Help

Masterlink Gateway Protocol - doesn't forward light command?

rated by 0 users
Not Answered This post has 0 verified answers | 15 Replies | 1 Follower

giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac posted on Fri, Jan 31 2020 4:24 PM

Hi there.

I have a Raspberry PI connected to a MLGW via the MLGW protocol (login on Ethernet from the RPi to the MLGW). Sending commands from the RPi to MLGW works fine, as well as the RPi receives "configuration change" messages, so the actual connection and protocol seems to be working. 

However, it seems like the MLGW does not forward the Light commands from my NL units to the protocol connection.

I see the light command from my Network Link unit show up in the MLGW "Monitor" log (so the MLGW receives the light command), but the RPi never receives the command on the protocol connection. 

How do I make the MLGW forward the light commands to the RPi? 

I tried with macros, but there seems to be no way for a macro to send messages through the MLGW protocol connection.

 

Thanks!

Giovanni

 

All Replies

frog
Top 150 Contributor
Camberley UK
538 Posts
OFFLINE
Founder
frog replied on Thu, Feb 13 2020 7:25 PM

I’m getting Light packages into a raspberry (I’m connecting via port 9000) from a Beosystem 4, so something else must be happening here - if it is hitting the monitor, then the NL device is set up to forward MLGW messages correctly.

 What is the NL device you are using?

what is the code you are using to connect?

giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Fri, Feb 14 2020 6:22 AM

Interesting. 

The device is a Beovision 55. They show up in the monitor, but not forwarded to the RPI over the 9000 port. Same thing for my Masterlink devices. Light commands show up in MLGW monitor but not forwarded. 

I'm using a Hass.io python script to connect.

firmware of MLGW is 2.24. Wondering if there is some secret setting.

I worked around it by creating macros on the MLGW, activated by the light commands, but that push REST commands to the RPi to activate scenes. Works fine but it's not what I wanted!

Giovanni

 

giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Fri, Feb 14 2020 6:26 AM

this is the code: https://github.com/simonkamronn/mlgw/blob/master/bangolufsen/media_player.py

frog
Top 150 Contributor
Camberley UK
538 Posts
OFFLINE
Founder
frog replied on Sun, Feb 16 2020 1:21 PM

Here's my code - which works with the Light command - 

 

https://rapidgator.net/file/f97262f9dfabca44aae57c59c829ca1d/mlgw_client.py.html

 

Zeus_72
Not Ranked
12 Posts
OFFLINE
Bronze Member

Hi Frog

I would like to study your program in python but the link you posted is no longer working. Could you share it again?   Could the program be adapted to work with home assistant?

giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Tue, Aug 25 2020 7:28 PM

There is code to run the bang Olufsen MLGW from Home Assistant here, which is maintained: https://github.com/simonkamronn/mlgw 

Zeus_72
Not Ranked
12 Posts
OFFLINE
Bronze Member
Thanks Giac

I saw the link you posted, but with the latest versions of home assistant it doesn't work well, at least on my raspberry. the script gives me a lot of problems and Lovelace B&O control card doesn't work at all. Although I don't have the skills, I wanted to study both Simon Kamronn's and Frog's scripts to understand if it was possible to modify them and make them work with my home assistant installation.
giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Tue, Aug 25 2020 8:53 PM

That's odd. It works fine with my home assistant. I'm on the latest version of HA. did you configure it correctly?

 

what is the error(s) you get?

 

 

Zeus_72
Not Ranked
12 Posts
OFFLINE
Bronze Member
Hi Giac

maybe it is better that I tell you my configuration and then tell you the errors I have.

I installed home assistant core on a raspberry pi 4. the home assistant core is a little different from the iso hassio, and maybe this could be the problem.

The errors are:

- In B&O entity settings appears "This entity does not have a unique ID, therefore its settings cannot be managed from the UI".

- The home assistant interface does not report the status of the B&O device. I try to explain, if I turn on Beovision 7 from home assistant, the interface shows the status "on" and the TV turns on but if I turn off Beovision 7 from Beo4, the home assistant does not change the status to "off".

- I installed the plugin for lovelace UI but the media control I am going to create has the following error "Attemped to assign to readonly property"

thanks again for your time

P.S. se ho capito bene dovresti essere anche tu italiano. Se così fosse potremmo continuare la conversazione in questa nobile lingua Smile e spostarci nel forum a noi dedicato.

Grazie ancora dell’aiuto
giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Wed, Aug 26 2020 9:19 PM

Ciao,

I'd rather continue in English since it may be useful to others :-)

Masterlink devices unfortunately don't report when they are turned off to MLGW, so I haven't been able to make the return path work to update the status. I have the same issue with my Beosound 3000. Beosound only reports when some sources are activated (e.g. CD or RADIO are activated).

 

You should not need to install any plugin in Lovelace.

 

You only need to install __init__.py, manifest.json and media_player.py in the custom_components/bangolufsen directory, and a config entry in configuration.yaml, this is mine:

media_player:

  - platform: bangolufsen

    host: 192.168.1.10

    username: xxx

    password: xxx

    default_source: A.MEM

    available_sources:

      - A.MEM

      - CD

      - RADIO

    devices:

      - Living Room

      - Kitchen

      - Patio

      - Studio

      - TV Room

      - Bedroom

      - Bathroom

 

 

Then Lovelace should pick up the media player using the normal media_player UI element.

I use mini_media player as a UI element which is nicer.

https://github.com/kalkih/mini-media-player/blob/master/README.md

 

Zeus_72
Not Ranked
12 Posts
OFFLINE
Bronze Member
Ciao Yes - thumbs up

ok we continue in English.

I would like to understand if you also have this error in the Beo entities: - "This Entity Does Not Have at Unique ID, Therefore Its Settings Cannot Be Managed From The UI".

Another thing I would like to understand is whether the communication limit between the mlgw and home assistant is the script or the mlgw protocol.

Reading the MLGW Protocol specifications Rev3 I noticed two types of payloads that report the status of the ml device.

The value 0x02 reports the status of the audio and video source including standby while the value 0x05 communicates that all the devices have been turned off. If so then the limit would be the script and it could be improved.

The plugin I was referring to is the javascrip program “beo-control.js” also written by Simon Kamronn. Have you tried it?

just one more thing Smile if you have Frog’s code could you share it?

Thanks
giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Thu, Aug 27 2020 4:16 PM

1) I get that error too but it does not affect operation. Not all entities need a unique Id. you only need it if you want to persist settings which in this case we don't

2) it's a device thing. Some devices like don't implement the full protocol, ie they don't send a status change when they are turned off. the code actually is designed to handle the turn off packet if the device sends it. you can see exactly what is sent by devices by turning on "INFO" logging for your plugin and looking at the Home assistant logs.

3) you don't need beo-control.js, it's old code and doesn't work. You can just use the normal media player UI from Lovelace.

 

giac
Not Ranked
9 Posts
OFFLINE
Bronze Member
giac replied on Thu, Aug 27 2020 4:16 PM

frog's code 

 

#!/usr/bin/python           # This is mlgw_client.py file

#

# It connects to a Bang & Olufsen Masterlink Gateway and interprets the LIGHT button pressed on a remote control

# It then connects via JSON to a Domoticz home automation server to switch on/off/dim a particular light

 

import socket               # Import socket module

import time     # Import Time module for delays & time

import datetime     # Import time of day module

import json                 # Import JSON to connect to Domoticz

import urllib

import urllib2

import os     # Import OS calls library

import __main__

import sys

__author__  = 'Nigel Smith'

__version__ = '0.1'

 

#Debug Flag

debug = True

sniff = True               # Sniff MLGW packets and display

 

# Setup B&O datagrams

serno = '01390000'.decode('hex')

#BV10Standby ='0101030012004700'.decode('hex')

#BV10AppleTV ='0101030012008500'.decode('hex')

#BV10Sky =    '0101030012008A00'.decode('hex')

#BV10off=     '0101030012000C00'.decode('hex')

 

#mlgw address

hostname = ("192.168.0.22")           # Masterlink Gateway hostname

 

#Rooms

Lounge = 1

Office = 2

Bedroom = 7

Dining = 4

Bathroom =5

Garden = 6

 

#Lights

RoomLight = 12

LoungeLight = 78

OfficeLight = [[12,False],[ 12, False], [15, False], [16, False]]

BlindLight = 194

VerandaLight = 17

BathroomLight = 45

GardenLight = 322

BedroomLight = 20

#Buttons

 

BOLightON = 155

BOLightOFF = 54

BOLightUP = 30

BOLightDN = 31

BOTV = 138

KeyRelease = 126

PanelOFF = 88

Exit = 127

Menu = 92

BOLightLeft = 50

BOLightRight = 52

BOGO = 53

BOSelect = 19

ButtonDict = {1:'One', 2:'Two', 3:'Three', 4:'Four', 5:'Five', 6:'Six', 7:'Seven', 8:'Eight', 9:'Nine', 0:'Zero',\

              30:'B&O Light UP', 31:'B&O Light Down', 50:'Left Arrow', 52:'Right Arrow', 54:'B&O Light OFF', \

              88:'Panel OFF', 92:'Menu', 126:'Key Release', 127:'Exit', 155:'B&O Light ON', 19:'Select'}

RoomDict = {1:'Lounge', 2:'Office', 8:'Bedroom', 4:'En-Suite Bathroom', 5:'Family Bathroom', 6:'Garden'}

#Times

on_time = datetime.time(17,30)

off_time = datetime.time(5,00)

 

grouplight = False

 

class switch(object):

   value = None

   def __new__(class_, value):

      class_.value = value

      return True

 

def case(*args):

      return any((arg == switch.value for arg in args))

 

def ByteToHex(byteStr):

   hex =[]   

   for aChar in byteStr:

      hex.append("%02X " % ord(aChar))

   return ''.join(hex).strip()

 

def SetLight(Lmp, opt, dimlvl,groups):

   if (opt == 'dim'):

     LightCMD="http://192.168.0.52:8080/json.htm?type=command&param=switchlight&idx="+str(Lmp)+"&switchcmd=Set%20Level&level="+dimlvl

   else:

if groups:

     LightCMD="http://192.168.0.52:8080/json.htm?type=command&param=switchscene&idx="+str(Lmp)+"&switchcmd="+opt+"&level=0"

else:

     LightCMD="http://192.168.0.52:8080/json.htm?type=command&param=switchlight&idx="+str(Lmp)+"&switchcmd="+opt+"&level=0"

   if debug:

     print LightCMD

   return LightCMD

 

def GetMLGWStatus():

   MStatus =ByteToHex(s.recv(255))

   if debug or sniff:

      print time.strftime("%c"), '____', MStatus

   return MStatus

 

def isLightCommand(Mstatus):

   if (int(Mstatus[3:5],16) == 4):

      return True

   else:

      return False

 

def getRoom(Mstatus):

    return int(Mstatus[12:14],16)

 

def getLightButton(Mstatus):

    if int(Mstatus[3:5]) <> 5:

      buttonkey = int(Mstatus[18:20],16)

      if debug:

         if ButtonDict.has_key(buttonkey):

            print current_time,Mstatus, '--','The button',ButtonDict[buttonkey],'was pressed in the',RoomDict[getRoom(Mstatus)]

         else:

            print Mstatus, '--''Unknown Key', buttonkey

      return int(Mstatus[18:20],16)

    else:

      return 0

# First check to see if program is running - if so - exit

try:

    if len( os.popen( "ps -aef | grep -i "+sys.argv[0]+" | grep -v 'grep' | awk '{ print $3 }'" ).read().strip().split( '\n' ) ) > 1:

        print sys.argv[0],"already running"

        raise SystemExit(0)

except Exception, e:

        raise e

 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)         # Create a socket object

try:

   host = socket.gethostbyname(hostname) # Connect to Mlgw.local

   port = 9000                           # Connect to MLGW Port

   if debug:

      print "Connecting to: ",host, port

except socket.gaierror,err:

   print "cannot resolve hostname: ",hostname,err

 

s.connect((hostname, port))

s.send(serno)

print ' '

print 'MLGW to Domoticz gateway'

print 'V1.0 - Nigel Smith, 26 Mar 2014'

print 'MLGW Serial Number:      ____',s.recv(255)

print 'Waiting for MLGW'

FirstTime = True

while True:

  MLGWStat = GetMLGWStatus()

  current_time = datetime.datetime.now().time()

  ButtonPressed = getLightButton(MLGWStat)

  if (ButtonPressed >0):

   if debug:

     print current_time

   if (isLightCommand(MLGWStat) & ButtonDict.has_key(int(MLGWStat[18:20],16))):

      while switch (getRoom(MLGWStat)):

        if case(Lounge):

           Room = 'Lounge'

           RoomLight = LoungeLight

   grouplight = False

           break

        if case(Office):

           Room = 'Office'

           RoomLight = OfficeLight[0][0]

   grouplight = False

           break

        if case(Bedroom):

   RoomLight = BedroomLight

           Room = 'Bedroom'

           grouplight = True

   break

        if case(Garden):

           Room = 'Garden'

           RoomLight = GardenLight

           grouplight = False

           break

        if case(Bathroom):

           Room = 'Bathroom'

           RoomLight = BathroomLight

   grouplight = False

           break

      if debug:

         print 'Button', ButtonPressed, 'Room', Room, RoomLight

      while switch (ButtonPressed):

        if case(BOLightON, BOGO, BOSelect):

           if FirstTime == True:

              FirstTime = False

              Button = 'First'

              break

           else:

              Button = 'ON'

              if Room == 'Office':

                 OfficeLight[1][1] = True

              if Room == 'Bedroom' or Room == 'Garden':

                 urllib2.urlopen(SetLight(RoomLight,'On','32', grouplight)) #Switch (relay)

              else:

                 urllib2.urlopen(SetLight(RoomLight,'dim','32', grouplight)) #Max brightness

              break

        if case(BOLightOFF):

           Button = 'OFF'

           FirstTime = True

           if case(BOLightOFF) and Room == 'Office':

             urllib2.urlopen('http://192.168.0.52:8080/json.htm?type=command&param=switchscene&idx=6&switchcmd=Off')

             for n in range(len(OfficeLight)):

                OfficeLightNo - thumbs down[1] = False

             break

           if case(BOLightOFF) and (Room == 'Bathroom' or Room == 'Garden' or Room == 'Lounge' or Room == 'Bedroom'):

             urllib2.urlopen(SetLight(RoomLight, 'Off',0, grouplight))

             break

           break

        if case(1,2,3) and Room == 'Office':

           FirstTime = True

           RoomLight = OfficeLight[ButtonPressed][0]

           OfficeLight[ButtonPressed][1] = True

           urllib2.urlopen(SetLight(RoomLight,'dim','32', grouplight)) #Max brightness

           break

        if case(4) and Room == 'Office':

           FirstTime = True

           urllib2.urlopen('http://192.168.0.52:8080/json.htm?type=command&param=switchscene&idx=6&switchcmd=On')

           for n in range(len(OfficeLight)):

                OfficeLightNo - thumbs down[1] = True

           break

        if case(5,6,7,8,9,0) and Room == 'Office':

           break

        if case(50,52,92):

           break

        if case(1,2,3,4,5,6,7,8,9, 0) and Room == 'Lounge':

           FirstTime = True

           Button = str(int(round((9 - getLightButton(MLGWStat)+1) *3.2)))   #change value from 0-9 to 32 to 1 - Bright to dim

           urllib2.urlopen(SetLight(RoomLight,'dim',Button, grouplight))

           break

        if case(BOLightUP) and Room == 'Lounge':

           urllib2.urlopen(SetLight(VerandaLight,'On',0, grouplight))

           break

        if case(BOLightDN) and Room == 'Lounge':

           urllib2.urlopen(SetLight(VerandaLight,'Off',0, grouplight))

           break

        if case(BOLightUP) and Room == 'Office':

           FirstTime = True

           urllib2.urlopen(SetLight(BlindLight,'Off',0, grouplight))     #Toggle Blinds

           break

        if case(BOLightDN) and Room == 'Office':

           FirstTime = True

           urllib2.urlopen(SetLight(BlindLight,'On',0, grouplight))     #Toggle Blinds

           break

        if case(KeyRelease):

           Button = 'Key Release'

           break

        if case(PanelOFF):

           Button = 'PANEL OFF'

           break

        if case(Exit):

           Button = 'Exit'

           Looping = False

           break

      if debug:

           print '>>>', Button, 'pressed in ', Room

   else:

      if debug:

           print ''

s.close                     # Close the socket when done

 

Zeus_72
Not Ranked
12 Posts
OFFLINE
Bronze Member
In summary, for lovelace I don't have to use beo-control.js and the "unique id" error is not relevant.

Only problem is that I don't get any feedback when I use beo4 not only when I put the device in standby but also when I change source.

I will check all the steps I have made and look for where the issue is hidden.

thanks again for all the help you gave me

Page 1 of 2 (16 items) 1 2 Next > | RSS
Beoworld Security Certificate

SSL